[lld] r309311 - Merge OutputSectionCommand and OutputSection.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 27 12:22:44 PDT 2017


Author: rafael
Date: Thu Jul 27 12:22:43 2017
New Revision: 309311

URL: http://llvm.org/viewvc/llvm-project?rev=309311&view=rev
Log:
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.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/MapFile.cpp
    lld/trunk/ELF/MapFile.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/Relocations.h
    lld/trunk/ELF/ScriptParser.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Jul 27 12:22:43 2017
@@ -27,7 +27,6 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/Casting.h"
-#include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
@@ -85,27 +84,26 @@ static SymbolBody *addRegular(SymbolAssi
   return Sym->body();
 }
 
-OutputSectionCommand *
-LinkerScript::createOutputSectionCommand(StringRef Name, StringRef Location) {
-  OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
-  OutputSectionCommand *Cmd;
-  if (CmdRef && CmdRef->Location.empty()) {
+OutputSection *LinkerScript::createOutputSection(StringRef Name,
+                                                 StringRef Location) {
+  OutputSection *&SecRef = NameToOutputSection[Name];
+  OutputSection *Sec;
+  if (SecRef && SecRef->Location.empty()) {
     // There was a forward reference.
-    Cmd = CmdRef;
+    Sec = SecRef;
   } else {
-    Cmd = make<OutputSectionCommand>(Name);
-    if (!CmdRef)
-      CmdRef = Cmd;
+    Sec = make<OutputSection>(Name, SHT_PROGBITS, 0);
+    if (!SecRef)
+      SecRef = Sec;
   }
-  Cmd->Location = Location;
-  return Cmd;
+  Sec->Location = Location;
+  return Sec;
 }
 
-OutputSectionCommand *
-LinkerScript::getOrCreateOutputSectionCommand(StringRef Name) {
-  OutputSectionCommand *&CmdRef = NameToOutputSectionCommand[Name];
+OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) {
+  OutputSection *&CmdRef = NameToOutputSection[Name];
   if (!CmdRef)
-    CmdRef = make<OutputSectionCommand>(Name);
+    CmdRef = make<OutputSection>(Name, SHT_PROGBITS, 0);
   return CmdRef;
 }
 
@@ -159,19 +157,6 @@ bool SymbolAssignment::classof(const Bas
   return C->Kind == AssignmentKind;
 }
 
-bool OutputSectionCommand::classof(const BaseCommand *C) {
-  return C->Kind == OutputSectionKind;
-}
-
-// Fill [Buf, Buf + Size) with Filler.
-// This is used for linker script "=fillexp" command.
-static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
-  size_t I = 0;
-  for (; I + 4 < Size; I += 4)
-    memcpy(Buf + I, &Filler, 4);
-  memcpy(Buf + I, &Filler, Size - I);
-}
-
 bool InputSectionDescription::classof(const BaseCommand *C) {
   return C->Kind == InputSectionKind;
 }
@@ -199,19 +184,6 @@ bool LinkerScript::shouldKeep(InputSecti
   return false;
 }
 
-// If an input string is in the form of "foo.N" where N is a number,
-// return N. Otherwise, returns 65536, which is one greater than the
-// lowest priority.
-static int getPriority(StringRef S) {
-  size_t Pos = S.rfind('.');
-  if (Pos == StringRef::npos)
-    return 65536;
-  int V;
-  if (!to_integer(S.substr(Pos + 1), V, 10))
-    return 65536;
-  return V;
-}
-
 // A helper function for the SORT() command.
 static std::function<bool(InputSectionBase *, InputSectionBase *)>
 getComparator(SortSectionPolicy K) {
@@ -325,7 +297,7 @@ void LinkerScript::discard(ArrayRef<Inpu
 }
 
 std::vector<InputSectionBase *>
-LinkerScript::createInputSectionList(OutputSectionCommand &OutCmd) {
+LinkerScript::createInputSectionList(OutputSection &OutCmd) {
   std::vector<InputSectionBase *> Ret;
 
   for (BaseCommand *Base : OutCmd.Commands) {
@@ -368,12 +340,12 @@ void LinkerScript::processCommands(Outpu
       continue;
     }
 
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I])) {
-      std::vector<InputSectionBase *> V = createInputSectionList(*Cmd);
+    if (auto *Sec = dyn_cast<OutputSection>(Opt.Commands[I])) {
+      std::vector<InputSectionBase *> V = createInputSectionList(*Sec);
 
       // The output section name `/DISCARD/' is special.
       // Any input section assigned to it is discarded.
-      if (Cmd->Name == "/DISCARD/") {
+      if (Sec->Name == "/DISCARD/") {
         discard(V);
         continue;
       }
@@ -385,7 +357,7 @@ void LinkerScript::processCommands(Outpu
       //
       // Because we'll iterate over Commands many more times, the easiest
       // way to "make it as if it wasn't present" is to just remove it.
-      if (!matchConstraints(V, Cmd->Constraint)) {
+      if (!matchConstraints(V, Sec->Constraint)) {
         for (InputSectionBase *S : V)
           S->Assigned = false;
         Opt.Commands.erase(Opt.Commands.begin() + I);
@@ -395,37 +367,32 @@ void LinkerScript::processCommands(Outpu
 
       // A directive may contain symbol definitions like this:
       // ".foo : { ...; bar = .; }". Handle them.
-      for (BaseCommand *Base : Cmd->Commands)
+      for (BaseCommand *Base : Sec->Commands)
         if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base))
           addSymbol(OutCmd);
 
       // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
       // is given, input sections are aligned to that value, whether the
       // given value is larger or smaller than the original section alignment.
-      if (Cmd->SubalignExpr) {
-        uint32_t Subalign = Cmd->SubalignExpr().getValue();
+      if (Sec->SubalignExpr) {
+        uint32_t Subalign = Sec->SubalignExpr().getValue();
         for (InputSectionBase *S : V)
           S->Alignment = Subalign;
       }
 
       // Add input sections to an output section.
       for (InputSectionBase *S : V)
-        Factory.addInputSec(S, Cmd->Name, Cmd->Sec);
-      if (OutputSection *Sec = Cmd->Sec) {
-        assert(Sec->SectionIndex == INT_MAX);
-        Sec->SectionIndex = I;
-        if (Cmd->Noload)
-          Sec->Type = SHT_NOBITS;
-        SecToCommand[Sec] = Cmd;
-      }
+        Factory.addInputSec(S, Sec->Name, Sec);
+      assert(Sec->SectionIndex == INT_MAX);
+      Sec->SectionIndex = I;
+      if (Sec->Noload)
+        Sec->Type = SHT_NOBITS;
     }
   }
   CurAddressState = nullptr;
 }
 
 void LinkerScript::fabricateDefaultCommands() {
-  std::vector<BaseCommand *> Commands;
-
   // Define start address
   uint64_t StartAddr = -1;
 
@@ -435,33 +402,15 @@ void LinkerScript::fabricateDefaultComma
   for (auto &KV : Config->SectionStartMap)
     StartAddr = std::min(StartAddr, KV.second);
 
-  Commands.push_back(make<SymbolAssignment>(
-      ".",
-      [=] {
-        return std::min(StartAddr, Config->ImageBase + elf::getHeaderSize());
-      },
-      ""));
-
-  // For each OutputSection that needs a VA fabricate an OutputSectionCommand
-  // with an InputSectionDescription describing the InputSections
-  for (OutputSection *Sec : OutputSections) {
-    auto *OSCmd = createOutputSectionCommand(Sec->Name, "<internal>");
-    OSCmd->Sec = Sec;
-    SecToCommand[Sec] = OSCmd;
-
-    Commands.push_back(OSCmd);
-    if (Sec->Sections.size()) {
-      auto *ISD = make<InputSectionDescription>("");
-      OSCmd->Commands.push_back(ISD);
-      for (InputSection *ISec : Sec->Sections) {
-        ISD->Sections.push_back(ISec);
-        ISec->Assigned = true;
-      }
-    }
-  }
-  // SECTIONS commands run before other non SECTIONS commands
-  Commands.insert(Commands.end(), Opt.Commands.begin(), Opt.Commands.end());
-  Opt.Commands = std::move(Commands);
+  Opt.Commands.insert(Opt.Commands.begin(),
+                      make<SymbolAssignment>(".",
+                                             [=] {
+                                               return std::min(
+                                                   StartAddr,
+                                                   Config->ImageBase +
+                                                       elf::getHeaderSize());
+                                             },
+                                             ""));
 }
 
 // Add sections that didn't match any sections command.
@@ -473,35 +422,21 @@ void LinkerScript::addOrphanSections(Out
     StringRef Name = getOutputSectionName(S->Name);
     auto End = Opt.Commands.begin() + NumCommands;
     auto I = std::find_if(Opt.Commands.begin(), End, [&](BaseCommand *Base) {
-      if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-        return Cmd->Name == Name;
+      if (auto *Sec = dyn_cast<OutputSection>(Base))
+        return Sec->Name == Name;
       return false;
     });
-    OutputSectionCommand *Cmd;
     if (I == End) {
       Factory.addInputSec(S, Name);
       OutputSection *Sec = S->getOutputSection();
       assert(Sec->SectionIndex == INT_MAX);
-      OutputSectionCommand *&CmdRef = SecToCommand[Sec];
-      if (!CmdRef) {
-        CmdRef = createOutputSectionCommand(Sec->Name, "<internal>");
-        CmdRef->Sec = Sec;
-        Opt.Commands.push_back(CmdRef);
-      }
-      Cmd = CmdRef;
     } else {
-      Cmd = cast<OutputSectionCommand>(*I);
-      Factory.addInputSec(S, Name, Cmd->Sec);
-      if (OutputSection *Sec = Cmd->Sec) {
-        SecToCommand[Sec] = Cmd;
-        unsigned Index = std::distance(Opt.Commands.begin(), I);
-        assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
-        Sec->SectionIndex = Index;
-      }
+      OutputSection *Sec = cast<OutputSection>(*I);
+      Factory.addInputSec(S, Name, Sec);
+      unsigned Index = std::distance(Opt.Commands.begin(), I);
+      assert(Sec->SectionIndex == INT_MAX || Sec->SectionIndex == Index);
+      Sec->SectionIndex = Index;
     }
-    auto *ISD = make<InputSectionDescription>("");
-    ISD->Sections.push_back(cast<InputSection>(S));
-    Cmd->Commands.push_back(ISD);
   }
 }
 
@@ -605,14 +540,14 @@ void LinkerScript::process(BaseCommand &
 // This function searches for a memory region to place the given output
 // section in. If found, a pointer to the appropriate memory region is
 // returned. Otherwise, a nullptr is returned.
-MemoryRegion *LinkerScript::findMemoryRegion(OutputSectionCommand *Cmd) {
+MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {
   // If a memory region name was specified in the output section command,
   // then try to find that region first.
-  if (!Cmd->MemoryRegionName.empty()) {
-    auto It = Opt.MemoryRegions.find(Cmd->MemoryRegionName);
+  if (!Sec->MemoryRegionName.empty()) {
+    auto It = Opt.MemoryRegions.find(Sec->MemoryRegionName);
     if (It != Opt.MemoryRegions.end())
       return &It->second;
-    error("memory region '" + Cmd->MemoryRegionName + "' not declared");
+    error("memory region '" + Sec->MemoryRegionName + "' not declared");
     return nullptr;
   }
 
@@ -622,7 +557,6 @@ MemoryRegion *LinkerScript::findMemoryRe
   if (Opt.MemoryRegions.empty())
     return nullptr;
 
-  OutputSection *Sec = Cmd->Sec;
   // See if a region can be found by matching section flags.
   for (auto &Pair : Opt.MemoryRegions) {
     MemoryRegion &M = Pair.second;
@@ -638,22 +572,18 @@ MemoryRegion *LinkerScript::findMemoryRe
 
 // 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) {
-  OutputSection *Sec = Cmd->Sec;
-  if (!Sec)
-    return;
-
+void LinkerScript::assignOffsets(OutputSection *Sec) {
   if (!(Sec->Flags & SHF_ALLOC))
     Dot = 0;
-  else if (Cmd->AddrExpr)
-    setDot(Cmd->AddrExpr, Cmd->Location, false);
+  else if (Sec->AddrExpr)
+    setDot(Sec->AddrExpr, Sec->Location, false);
 
-  if (Cmd->LMAExpr) {
+  if (Sec->LMAExpr) {
     uint64_t D = Dot;
-    CurAddressState->LMAOffset = [=] { return Cmd->LMAExpr().getValue() - D; };
+    CurAddressState->LMAOffset = [=] { return Sec->LMAExpr().getValue() - D; };
   }
 
-  CurAddressState->MemRegion = Cmd->MemRegion;
+  CurAddressState->MemRegion = Sec->MemRegion;
   if (CurAddressState->MemRegion)
     Dot = CurAddressState->MemRegionOffset[CurAddressState->MemRegion];
   switchTo(Sec);
@@ -663,7 +593,7 @@ void LinkerScript::assignOffsets(OutputS
   if (CurAddressState->OutSec->Flags & SHF_COMPRESSED)
     return;
 
-  for (BaseCommand *C : Cmd->Commands)
+  for (BaseCommand *C : Sec->Commands)
     process(*C);
 }
 
@@ -674,16 +604,16 @@ void LinkerScript::removeEmptyCommands()
   // clutter the output.
   // We instead remove trivially empty sections. The bfd linker seems even
   // more aggressive at removing them.
-  auto Pos = std::remove_if(
-      Opt.Commands.begin(), Opt.Commands.end(), [&](BaseCommand *Base) {
-        if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-          return Cmd->Sec == nullptr;
-        return false;
-      });
+  auto Pos = std::remove_if(Opt.Commands.begin(), Opt.Commands.end(),
+                            [&](BaseCommand *Base) {
+                              if (auto *Sec = dyn_cast<OutputSection>(Base))
+                                return !Sec->Live;
+                              return false;
+                            });
   Opt.Commands.erase(Pos, Opt.Commands.end());
 }
 
-static bool isAllSectionDescription(const OutputSectionCommand &Cmd) {
+static bool isAllSectionDescription(const OutputSection &Cmd) {
   for (BaseCommand *Base : Cmd.Commands)
     if (!isa<InputSectionDescription>(*Base))
       return false;
@@ -698,32 +628,31 @@ void LinkerScript::adjustSectionsBeforeS
   uint64_t Flags = SHF_ALLOC;
 
   for (int I = 0, E = Opt.Commands.size(); I != E; ++I) {
-    auto *Cmd = dyn_cast<OutputSectionCommand>(Opt.Commands[I]);
-    if (!Cmd)
+    auto *Sec = dyn_cast<OutputSection>(Opt.Commands[I]);
+    if (!Sec)
       continue;
-    if (OutputSection *Sec = Cmd->Sec) {
+    if (Sec->Live) {
       Flags = Sec->Flags;
       continue;
     }
 
-    if (isAllSectionDescription(*Cmd))
+    if (isAllSectionDescription(*Sec))
       continue;
 
-    auto *OutSec = make<OutputSection>(Cmd->Name, SHT_PROGBITS, Flags);
-    OutSec->SectionIndex = I;
-    Cmd->Sec = OutSec;
-    SecToCommand[OutSec] = Cmd;
+    Sec->Live = true;
+    Sec->SectionIndex = I;
+    Sec->Flags = Flags;
   }
 }
 
 void LinkerScript::adjustSectionsAfterSorting() {
   // Try and find an appropriate memory region to assign offsets in.
   for (BaseCommand *Base : Opt.Commands) {
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base)) {
-      Cmd->MemRegion = findMemoryRegion(Cmd);
+    if (auto *Sec = dyn_cast<OutputSection>(Base)) {
+      Sec->MemRegion = findMemoryRegion(Sec);
       // Handle align (e.g. ".foo : ALIGN(16) { ... }").
-      if (Cmd->AlignExpr && Cmd->Sec)
-        Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
+      if (Sec->AlignExpr)
+        Sec->updateAlignment(Sec->AlignExpr().getValue());
     }
   }
 
@@ -743,18 +672,17 @@ void LinkerScript::adjustSectionsAfterSo
   // Walk the commands and propagate the program headers to commands that don't
   // explicitly specify them.
   for (BaseCommand *Base : Opt.Commands) {
-    auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
-    if (!Cmd)
+    auto *Sec = dyn_cast<OutputSection>(Base);
+    if (!Sec)
       continue;
 
-    if (Cmd->Phdrs.empty()) {
-      OutputSection *Sec = Cmd->Sec;
+    if (Sec->Phdrs.empty()) {
       // To match the bfd linker script behaviour, only propagate program
       // headers to sections that are allocated.
-      if (Sec && (Sec->Flags & SHF_ALLOC))
-        Cmd->Phdrs = DefPhdrs;
+      if (Sec->Flags & SHF_ALLOC)
+        Sec->Phdrs = DefPhdrs;
     } else {
-      DefPhdrs = Cmd->Phdrs;
+      DefPhdrs = Sec->Phdrs;
     }
   }
 
@@ -763,11 +691,9 @@ void LinkerScript::adjustSectionsAfterSo
 
 void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {
   uint64_t Min = std::numeric_limits<uint64_t>::max();
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec->Flags & SHF_ALLOC)
       Min = std::min<uint64_t>(Min, Sec->Addr);
-  }
 
   auto It = llvm::find_if(
       Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; });
@@ -785,19 +711,16 @@ void LinkerScript::allocateHeaders(std::
 
   assert(FirstPTLoad->First == Out::ElfHeader);
   OutputSection *ActualFirst = nullptr;
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections) {
     if (Sec->FirstInPtLoad == Out::ElfHeader) {
       ActualFirst = Sec;
       break;
     }
   }
   if (ActualFirst) {
-    for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-      OutputSection *Sec = Cmd->Sec;
+    for (OutputSection *Sec : OutputSections)
       if (Sec->FirstInPtLoad == Out::ElfHeader)
         Sec->FirstInPtLoad = ActualFirst;
-    }
     FirstPTLoad->First = ActualFirst;
   } else {
     Phdrs.erase(It);
@@ -839,8 +762,7 @@ void LinkerScript::assignAddresses() {
       continue;
     }
 
-    auto *Cmd = cast<OutputSectionCommand>(Base);
-    assignOffsets(Cmd);
+    assignOffsets(cast<OutputSection>(Base));
   }
   CurAddressState = nullptr;
 }
@@ -868,10 +790,9 @@ std::vector<PhdrEntry *> LinkerScript::c
   }
 
   // Add output sections to program headers.
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
+  for (OutputSection *Sec : OutputSections) {
     // Assign headers specified by linker script
-    for (size_t Id : getPhdrIndices(Cmd)) {
-      OutputSection *Sec = Cmd->Sec;
+    for (size_t Id : getPhdrIndices(Sec)) {
       Ret[Id]->add(Sec);
       if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
         Ret[Id]->p_flags |= Sec->getPhdrFlags();
@@ -891,273 +812,6 @@ bool LinkerScript::ignoreInterpSection()
   return true;
 }
 
-OutputSectionCommand *LinkerScript::getCmd(OutputSection *Sec) const {
-  auto I = SecToCommand.find(Sec);
-  if (I == SecToCommand.end())
-    return nullptr;
-  return I->second;
-}
-
-void OutputSectionCommand::sort(std::function<int(InputSectionBase *S)> Order) {
-  typedef std::pair<unsigned, InputSection *> Pair;
-  auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
-
-  std::vector<Pair> V;
-  assert(Commands.size() == 1);
-  auto *ISD = cast<InputSectionDescription>(Commands[0]);
-  for (InputSection *S : ISD->Sections)
-    V.push_back({Order(S), S});
-  std::stable_sort(V.begin(), V.end(), Comp);
-  ISD->Sections.clear();
-  for (Pair &P : V)
-    ISD->Sections.push_back(P.second);
-}
-
-// Returns true if S matches /Filename.?\.o$/.
-static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
-  if (!S.endswith(".o"))
-    return false;
-  S = S.drop_back(2);
-  if (S.endswith(Filename))
-    return true;
-  return !S.empty() && S.drop_back().endswith(Filename);
-}
-
-static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
-static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
-
-// .ctors and .dtors are sorted by this priority from highest to lowest.
-//
-//  1. The section was contained in crtbegin (crtbegin contains
-//     some sentinel value in its .ctors and .dtors so that the runtime
-//     can find the beginning of the sections.)
-//
-//  2. The section has an optional priority value in the form of ".ctors.N"
-//     or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
-//     they are compared as string rather than number.
-//
-//  3. The section is just ".ctors" or ".dtors".
-//
-//  4. The section was contained in crtend, which contains an end marker.
-//
-// In an ideal world, we don't need this function because .init_array and
-// .ctors are duplicate features (and .init_array is newer.) However, there
-// are too many real-world use cases of .ctors, so we had no choice to
-// support that with this rather ad-hoc semantics.
-static bool compCtors(const InputSection *A, const InputSection *B) {
-  bool BeginA = isCrtbegin(A->File->getName());
-  bool BeginB = isCrtbegin(B->File->getName());
-  if (BeginA != BeginB)
-    return BeginA;
-  bool EndA = isCrtend(A->File->getName());
-  bool EndB = isCrtend(B->File->getName());
-  if (EndA != EndB)
-    return EndB;
-  StringRef X = A->Name;
-  StringRef Y = B->Name;
-  assert(X.startswith(".ctors") || X.startswith(".dtors"));
-  assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
-  X = X.substr(6);
-  Y = Y.substr(6);
-  if (X.empty() && Y.empty())
-    return false;
-  return X < Y;
-}
-
-// Sorts input sections by the special rules for .ctors and .dtors.
-// Unfortunately, the rules are different from the one for .{init,fini}_array.
-// Read the comment above.
-void OutputSectionCommand::sortCtorsDtors() {
-  assert(Commands.size() == 1);
-  auto *ISD = cast<InputSectionDescription>(Commands[0]);
-  std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors);
-}
-
-// Sorts input sections by section name suffixes, so that .foo.N comes
-// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
-// We want to keep the original order if the priorities are the same
-// because the compiler keeps the original initialization order in a
-// translation unit and we need to respect that.
-// For more detail, read the section of the GCC's manual about init_priority.
-void OutputSectionCommand::sortInitFini() {
-  // Sort sections by priority.
-  sort([](InputSectionBase *S) { return getPriority(S->Name); });
-}
-
-uint32_t OutputSectionCommand::getFiller() {
-  if (Filler)
-    return *Filler;
-  if (Sec->Flags & SHF_EXECINSTR)
-    return Target->TrapInstr;
-  return 0;
-}
-
-static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
-  if (Size == 1)
-    *Buf = Data;
-  else if (Size == 2)
-    write16(Buf, Data, Config->Endianness);
-  else if (Size == 4)
-    write32(Buf, Data, Config->Endianness);
-  else if (Size == 8)
-    write64(Buf, Data, Config->Endianness);
-  else
-    llvm_unreachable("unsupported Size argument");
-}
-
-static bool compareByFilePosition(InputSection *A, InputSection *B) {
-  // Synthetic doesn't have link order dependecy, stable_sort will keep it last
-  if (A->kind() == InputSectionBase::Synthetic ||
-      B->kind() == InputSectionBase::Synthetic)
-    return false;
-  InputSection *LA = A->getLinkOrderDep();
-  InputSection *LB = B->getLinkOrderDep();
-  OutputSection *AOut = LA->getParent();
-  OutputSection *BOut = LB->getParent();
-  if (AOut != BOut)
-    return AOut->SectionIndex < BOut->SectionIndex;
-  return LA->OutSecOff < LB->OutSecOff;
-}
-
-template <class ELFT>
-static void finalizeShtGroup(OutputSection *OS,
-                             ArrayRef<InputSection *> Sections) {
-  assert(Config->Relocatable && Sections.size() == 1);
-
-  // sh_link field for SHT_GROUP sections should contain the section index of
-  // the symbol table.
-  OS->Link = InX::SymTab->getParent()->SectionIndex;
-
-  // sh_info then contain index of an entry in symbol table section which
-  // provides signature of the section group.
-  ObjFile<ELFT> *Obj = Sections[0]->getFile<ELFT>();
-  ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
-  OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]);
-}
-
-template <class ELFT> void OutputSectionCommand::finalize() {
-  // Link order may be distributed across several InputSectionDescriptions
-  // but sort must consider them all at once.
-  std::vector<InputSection **> ScriptSections;
-  std::vector<InputSection *> Sections;
-  for (BaseCommand *Base : Commands)
-    if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
-      for (InputSection *&IS : ISD->Sections) {
-        ScriptSections.push_back(&IS);
-        Sections.push_back(IS);
-      }
-
-  if ((Sec->Flags & SHF_LINK_ORDER)) {
-    std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
-    for (int I = 0, N = Sections.size(); I < N; ++I)
-      *ScriptSections[I] = Sections[I];
-
-    // 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,
-    // all InputSections in the OutputSection have the same dependency.
-    if (auto *D = Sections.front()->getLinkOrderDep())
-      Sec->Link = D->getParent()->SectionIndex;
-  }
-
-  uint32_t Type = Sec->Type;
-  if (Type == SHT_GROUP) {
-    finalizeShtGroup<ELFT>(Sec, Sections);
-    return;
-  }
-
-  if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
-    return;
-
-  InputSection *First = Sections[0];
-  if (isa<SyntheticSection>(First))
-    return;
-
-  Sec->Link = InX::SymTab->getParent()->SectionIndex;
-  // sh_info for SHT_REL[A] sections should contain the section header index of
-  // the section to which the relocation applies.
-  InputSectionBase *S = First->getRelocatedSection();
-  Sec->Info = S->getOutputSection()->SectionIndex;
-  Sec->Flags |= SHF_INFO_LINK;
-}
-
-// Compress section contents if this section contains debug info.
-template <class ELFT> void OutputSectionCommand::maybeCompress() {
-  typedef typename ELFT::Chdr Elf_Chdr;
-
-  // Compress only DWARF debug sections.
-  if (!Config->CompressDebugSections || (Sec->Flags & SHF_ALLOC) ||
-      !Name.startswith(".debug_"))
-    return;
-
-  // Create a section header.
-  Sec->ZDebugHeader.resize(sizeof(Elf_Chdr));
-  auto *Hdr = reinterpret_cast<Elf_Chdr *>(Sec->ZDebugHeader.data());
-  Hdr->ch_type = ELFCOMPRESS_ZLIB;
-  Hdr->ch_size = Sec->Size;
-  Hdr->ch_addralign = Sec->Alignment;
-
-  // Write section contents to a temporary buffer and compress it.
-  std::vector<uint8_t> Buf(Sec->Size);
-  writeTo<ELFT>(Buf.data());
-  if (Error E = zlib::compress(toStringRef(Buf), Sec->CompressedData))
-    fatal("compress failed: " + llvm::toString(std::move(E)));
-
-  // Update section headers.
-  Sec->Size = sizeof(Elf_Chdr) + Sec->CompressedData.size();
-  Sec->Flags |= SHF_COMPRESSED;
-}
-
-template <class ELFT> void OutputSectionCommand::writeTo(uint8_t *Buf) {
-  if (Sec->Type == SHT_NOBITS)
-    return;
-
-  Sec->Loc = Buf;
-
-  // If -compress-debug-section is specified and if this is a debug seciton,
-  // we've already compressed section contents. If that's the case,
-  // just write it down.
-  if (!Sec->CompressedData.empty()) {
-    memcpy(Buf, Sec->ZDebugHeader.data(), Sec->ZDebugHeader.size());
-    memcpy(Buf + Sec->ZDebugHeader.size(), Sec->CompressedData.data(),
-           Sec->CompressedData.size());
-    return;
-  }
-
-  // Write leading padding.
-  std::vector<InputSection *> Sections;
-  for (BaseCommand *Cmd : Commands)
-    if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
-      for (InputSection *IS : ISD->Sections)
-        if (IS->Live)
-          Sections.push_back(IS);
-  uint32_t Filler = getFiller();
-  if (Filler)
-    fill(Buf, Sections.empty() ? Sec->Size : Sections[0]->OutSecOff, Filler);
-
-  parallelForEachN(0, Sections.size(), [=](size_t I) {
-    InputSection *IS = Sections[I];
-    IS->writeTo<ELFT>(Buf);
-
-    // Fill gaps between sections.
-    if (Filler) {
-      uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
-      uint8_t *End;
-      if (I + 1 == Sections.size())
-        End = Buf + Sec->Size;
-      else
-        End = Buf + Sections[I + 1]->OutSecOff;
-      fill(Start, End - Start, Filler);
-    }
-  });
-
-  // Linker scripts may have BYTE()-family commands with which you
-  // can write arbitrary bytes to the output. Process them if any.
-  for (BaseCommand *Base : Commands)
-    if (auto *Data = dyn_cast<BytesDataCommand>(Base))
-      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
-}
-
 ExprValue LinkerScript::getSymbolValue(const Twine &Loc, StringRef S) {
   if (S == ".")
     return {CurAddressState->OutSec, Dot - CurAddressState->OutSec->Addr, Loc};
@@ -1177,7 +831,7 @@ static const size_t NoPhdr = -1;
 
 // Returns indices of ELF headers containing specific section. Each index is a
 // zero based number of ELF header listed within PHDRS {} script block.
-std::vector<size_t> LinkerScript::getPhdrIndices(OutputSectionCommand *Cmd) {
+std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Cmd) {
   std::vector<size_t> Ret;
   for (StringRef PhdrName : Cmd->Phdrs) {
     size_t Index = getPhdrIndex(Cmd->Location, PhdrName);
@@ -1202,18 +856,3 @@ size_t LinkerScript::getPhdrIndex(const
     error(Loc + ": section header '" + PhdrName + "' is not listed in PHDRS");
   return NoPhdr;
 }
-
-template void OutputSectionCommand::writeTo<ELF32LE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF32BE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF64LE>(uint8_t *Buf);
-template void OutputSectionCommand::writeTo<ELF64BE>(uint8_t *Buf);
-
-template void OutputSectionCommand::maybeCompress<ELF32LE>();
-template void OutputSectionCommand::maybeCompress<ELF32BE>();
-template void OutputSectionCommand::maybeCompress<ELF64LE>();
-template void OutputSectionCommand::maybeCompress<ELF64BE>();
-
-template void OutputSectionCommand::finalize<ELF32LE>();
-template void OutputSectionCommand::finalize<ELF32BE>();
-template void OutputSectionCommand::finalize<ELF64LE>();
-template void OutputSectionCommand::finalize<ELF64BE>();

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Thu Jul 27 12:22:43 2017
@@ -114,37 +114,6 @@ struct MemoryRegion {
   uint32_t NegFlags;
 };
 
-struct OutputSectionCommand : BaseCommand {
-  OutputSectionCommand(StringRef Name)
-      : BaseCommand(OutputSectionKind), Name(Name) {}
-
-  static bool classof(const BaseCommand *C);
-
-  OutputSection *Sec = nullptr;
-  MemoryRegion *MemRegion = nullptr;
-  StringRef Name;
-  Expr AddrExpr;
-  Expr AlignExpr;
-  Expr LMAExpr;
-  Expr SubalignExpr;
-  std::vector<BaseCommand *> Commands;
-  std::vector<StringRef> Phdrs;
-  llvm::Optional<uint32_t> Filler;
-  ConstraintKind Constraint = ConstraintKind::NoConstraint;
-  std::string Location;
-  std::string MemoryRegionName;
-  bool Noload = false;
-
-  template <class ELFT> void finalize();
-  template <class ELFT> void writeTo(uint8_t *Buf);
-  template <class ELFT> void maybeCompress();
-  uint32_t getFiller();
-
-  void sort(std::function<int(InputSectionBase *S)> Order);
-  void sortInitFini();
-  void sortCtorsDtors();
-};
-
 // This struct represents one section match pattern in SECTIONS() command.
 // It can optionally have negative match pattern for EXCLUDED_FILE command.
 // Also it may be surrounded with SORT() command, so contains sorting rules.
@@ -236,8 +205,7 @@ class LinkerScript final {
     std::function<uint64_t()> LMAOffset;
     AddressState(const ScriptConfiguration &Opt);
   };
-  llvm::DenseMap<OutputSection *, OutputSectionCommand *> SecToCommand;
-  llvm::DenseMap<StringRef, OutputSectionCommand *> NameToOutputSectionCommand;
+  llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection;
 
   void assignSymbol(SymbolAssignment *Cmd, bool InSec);
   void setDot(Expr E, const Twine &Loc, bool InSec);
@@ -245,13 +213,12 @@ class LinkerScript final {
   std::vector<InputSection *>
   computeInputSections(const InputSectionDescription *);
 
-  std::vector<InputSectionBase *>
-  createInputSectionList(OutputSectionCommand &Cmd);
+  std::vector<InputSectionBase *> createInputSectionList(OutputSection &Cmd);
 
-  std::vector<size_t> getPhdrIndices(OutputSectionCommand *Cmd);
+  std::vector<size_t> getPhdrIndices(OutputSection *Sec);
   size_t getPhdrIndex(const Twine &Loc, StringRef PhdrName);
 
-  MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
+  MemoryRegion *findMemoryRegion(OutputSection *Sec);
 
   void switchTo(OutputSection *Sec);
   uint64_t advance(uint64_t Size, unsigned Align);
@@ -265,11 +232,9 @@ class LinkerScript final {
 
 public:
   bool ErrorOnMissingSection = false;
-  OutputSectionCommand *createOutputSectionCommand(StringRef Name,
-                                                   StringRef Location);
-  OutputSectionCommand *getOrCreateOutputSectionCommand(StringRef Name);
+  OutputSection *createOutputSection(StringRef Name, StringRef Location);
+  OutputSection *getOrCreateOutputSection(StringRef Name);
 
-  OutputSectionCommand *getCmd(OutputSection *Sec) const;
   bool hasPhdrsCommands() { return !Opt.PhdrsCommands.empty(); }
   uint64_t getDot() { return Dot; }
   void discard(ArrayRef<InputSectionBase *> V);
@@ -287,7 +252,7 @@ public:
   bool ignoreInterpSection();
 
   bool shouldKeep(InputSectionBase *S);
-  void assignOffsets(OutputSectionCommand *Cmd);
+  void assignOffsets(OutputSection *Sec);
   void assignAddresses();
   void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);
   void addSymbol(SymbolAssignment *Cmd);

Modified: lld/trunk/ELF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.cpp (original)
+++ lld/trunk/ELF/MapFile.cpp Thu Jul 27 12:22:43 2017
@@ -99,8 +99,7 @@ getSymbolStrings(ArrayRef<DefinedRegular
   return Ret;
 }
 
-template <class ELFT>
-void elf::writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script) {
+template <class ELFT> void elf::writeMapFile() {
   if (Config->MapFile.empty())
     return;
 
@@ -123,13 +122,12 @@ void elf::writeMapFile(llvm::ArrayRef<Ou
      << " Align Out     In      Symbol\n";
 
   // Print out file contents.
-  for (OutputSectionCommand *Cmd : Script) {
-    OutputSection *OSec = Cmd->Sec;
+  for (OutputSection *OSec : OutputSections) {
     writeHeader<ELFT>(OS, OSec->Addr, OSec->Size, OSec->Alignment);
     OS << OSec->Name << '\n';
 
     // Dump symbols for each input section.
-    for (BaseCommand *Base : Cmd->Commands) {
+    for (BaseCommand *Base : OSec->Commands) {
       auto *ISD = dyn_cast<InputSectionDescription>(Base);
       if (!ISD)
         continue;
@@ -144,7 +142,7 @@ void elf::writeMapFile(llvm::ArrayRef<Ou
   }
 }
 
-template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionCommand *>);
-template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionCommand *>);
+template void elf::writeMapFile<ELF32LE>();
+template void elf::writeMapFile<ELF32BE>();
+template void elf::writeMapFile<ELF64LE>();
+template void elf::writeMapFile<ELF64BE>();

Modified: lld/trunk/ELF/MapFile.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.h (original)
+++ lld/trunk/ELF/MapFile.h Thu Jul 27 12:22:43 2017
@@ -14,9 +14,8 @@
 
 namespace lld {
 namespace elf {
-struct OutputSectionCommand;
-template <class ELFT>
-void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
+class OutputSection;
+template <class ELFT> void writeMapFile();
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Thu Jul 27 12:22:43 2017
@@ -17,6 +17,7 @@
 #include "Target.h"
 #include "Threads.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/SHA1.h"
@@ -42,7 +43,6 @@ OutputSection *Out::InitArray;
 OutputSection *Out::FiniArray;
 
 std::vector<OutputSection *> elf::OutputSections;
-std::vector<OutputSectionCommand *> elf::OutputSectionCommands;
 
 uint32_t OutputSection::getPhdrFlags() const {
   uint32_t Ret = PF_R;
@@ -68,10 +68,13 @@ void OutputSection::writeHeaderTo(typena
 }
 
 OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
-    : SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
+    : BaseCommand(OutputSectionKind),
+      SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,
                   /*Info*/ 0,
                   /*Link*/ 0),
-      SectionIndex(INT_MAX) {}
+      SectionIndex(INT_MAX) {
+  Live = false;
+}
 
 static uint64_t updateOffset(uint64_t Off, InputSection *S) {
   Off = alignTo(Off, S->Alignment);
@@ -81,7 +84,7 @@ static uint64_t updateOffset(uint64_t Of
 
 void OutputSection::addSection(InputSection *S) {
   assert(S->Live);
-  Sections.push_back(S);
+  Live = true;
   S->Parent = this;
   this->updateAlignment(S->Alignment);
 
@@ -99,6 +102,14 @@ void OutputSection::addSection(InputSect
   // Probably we sholuld handle that as an error. But for now we just
   // pick the largest sh_entsize.
   this->Entsize = std::max(this->Entsize, S->Entsize);
+
+  if (!S->Assigned) {
+    S->Assigned = true;
+    if (Commands.empty() || !isa<InputSectionDescription>(Commands.back()))
+      Commands.push_back(make<InputSectionDescription>(""));
+    auto *ISD = cast<InputSectionDescription>(Commands.back());
+    ISD->Sections.push_back(S);
+  }
 }
 
 static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) {
@@ -220,7 +231,7 @@ void OutputSectionFactory::addInputSec(I
     return;
   }
 
-  if (Sec) {
+  if (Sec && Sec->Live) {
     if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
       error("incompatible section flags for " + Sec->Name + "\n>>> " +
             toString(IS) + ": 0x" + utohexstr(IS->Flags) +
@@ -238,8 +249,12 @@ void OutputSectionFactory::addInputSec(I
     }
     Sec->Flags |= IS->Flags;
   } else {
-    Sec = make<OutputSection>(OutsecName, IS->Type, IS->Flags);
-    OutputSections.push_back(Sec);
+    if (!Sec) {
+      Sec = Script->createOutputSection(OutsecName, "<internal>");
+      Script->Opt.Commands.push_back(Sec);
+    }
+    Sec->Type = IS->Type;
+    Sec->Flags = IS->Flags;
   }
 
   Sec->addSection(cast<InputSection>(IS));
@@ -271,7 +286,307 @@ uint64_t elf::getHeaderSize() {
   return Out::ElfHeader->Size + Out::ProgramHeaders->Size;
 }
 
+bool OutputSection::classof(const BaseCommand *C) {
+  return C->Kind == OutputSectionKind;
+}
+
+void OutputSection::sort(std::function<int(InputSectionBase *S)> Order) {
+  typedef std::pair<unsigned, InputSection *> Pair;
+  auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };
+
+  std::vector<Pair> V;
+  assert(Commands.size() == 1);
+  auto *ISD = cast<InputSectionDescription>(Commands[0]);
+  for (InputSection *S : ISD->Sections)
+    V.push_back({Order(S), S});
+  std::stable_sort(V.begin(), V.end(), Comp);
+  ISD->Sections.clear();
+  for (Pair &P : V)
+    ISD->Sections.push_back(P.second);
+}
+
+// Fill [Buf, Buf + Size) with Filler.
+// This is used for linker script "=fillexp" command.
+static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) {
+  size_t I = 0;
+  for (; I + 4 < Size; I += 4)
+    memcpy(Buf + I, &Filler, 4);
+  memcpy(Buf + I, &Filler, Size - I);
+}
+
+// Compress section contents if this section contains debug info.
+template <class ELFT> void OutputSection::maybeCompress() {
+  typedef typename ELFT::Chdr Elf_Chdr;
+
+  // Compress only DWARF debug sections.
+  if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) ||
+      !Name.startswith(".debug_"))
+    return;
+
+  // Create a section header.
+  ZDebugHeader.resize(sizeof(Elf_Chdr));
+  auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data());
+  Hdr->ch_type = ELFCOMPRESS_ZLIB;
+  Hdr->ch_size = Size;
+  Hdr->ch_addralign = Alignment;
+
+  // Write section contents to a temporary buffer and compress it.
+  std::vector<uint8_t> Buf(Size);
+  writeTo<ELFT>(Buf.data());
+  if (Error E = zlib::compress(toStringRef(Buf), CompressedData))
+    fatal("compress failed: " + llvm::toString(std::move(E)));
+
+  // Update section headers.
+  Size = sizeof(Elf_Chdr) + CompressedData.size();
+  Flags |= SHF_COMPRESSED;
+}
+
+static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {
+  if (Size == 1)
+    *Buf = Data;
+  else if (Size == 2)
+    write16(Buf, Data, Config->Endianness);
+  else if (Size == 4)
+    write32(Buf, Data, Config->Endianness);
+  else if (Size == 8)
+    write64(Buf, Data, Config->Endianness);
+  else
+    llvm_unreachable("unsupported Size argument");
+}
+
+template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {
+  if (Type == SHT_NOBITS)
+    return;
+
+  Loc = Buf;
+
+  // If -compress-debug-section is specified and if this is a debug seciton,
+  // we've already compressed section contents. If that's the case,
+  // just write it down.
+  if (!CompressedData.empty()) {
+    memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size());
+    memcpy(Buf + ZDebugHeader.size(), CompressedData.data(),
+           CompressedData.size());
+    return;
+  }
+
+  // Write leading padding.
+  std::vector<InputSection *> Sections;
+  for (BaseCommand *Cmd : Commands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))
+      for (InputSection *IS : ISD->Sections)
+        if (IS->Live)
+          Sections.push_back(IS);
+  uint32_t Filler = getFiller();
+  if (Filler)
+    fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);
+
+  parallelForEachN(0, Sections.size(), [=](size_t I) {
+    InputSection *IS = Sections[I];
+    IS->writeTo<ELFT>(Buf);
+
+    // Fill gaps between sections.
+    if (Filler) {
+      uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();
+      uint8_t *End;
+      if (I + 1 == Sections.size())
+        End = Buf + Size;
+      else
+        End = Buf + Sections[I + 1]->OutSecOff;
+      fill(Start, End - Start, Filler);
+    }
+  });
+
+  // Linker scripts may have BYTE()-family commands with which you
+  // can write arbitrary bytes to the output. Process them if any.
+  for (BaseCommand *Base : Commands)
+    if (auto *Data = dyn_cast<BytesDataCommand>(Base))
+      writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);
+}
+
+static bool compareByFilePosition(InputSection *A, InputSection *B) {
+  // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+  if (A->kind() == InputSectionBase::Synthetic ||
+      B->kind() == InputSectionBase::Synthetic)
+    return false;
+  InputSection *LA = A->getLinkOrderDep();
+  InputSection *LB = B->getLinkOrderDep();
+  OutputSection *AOut = LA->getParent();
+  OutputSection *BOut = LB->getParent();
+  if (AOut != BOut)
+    return AOut->SectionIndex < BOut->SectionIndex;
+  return LA->OutSecOff < LB->OutSecOff;
+}
+
+template <class ELFT>
+static void finalizeShtGroup(OutputSection *OS,
+                             ArrayRef<InputSection *> Sections) {
+  assert(Config->Relocatable && Sections.size() == 1);
+
+  // sh_link field for SHT_GROUP sections should contain the section index of
+  // the symbol table.
+  OS->Link = InX::SymTab->getParent()->SectionIndex;
+
+  // sh_info then contain index of an entry in symbol table section which
+  // provides signature of the section group.
+  ObjFile<ELFT> *Obj = Sections[0]->getFile<ELFT>();
+  ArrayRef<SymbolBody *> Symbols = Obj->getSymbols();
+  OS->Info = InX::SymTab->getSymbolIndex(Symbols[Sections[0]->Info - 1]);
+}
+
+template <class ELFT> void OutputSection::finalize() {
+  // Link order may be distributed across several InputSectionDescriptions
+  // but sort must consider them all at once.
+  std::vector<InputSection **> ScriptSections;
+  std::vector<InputSection *> Sections;
+  for (BaseCommand *Base : Commands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+      for (InputSection *&IS : ISD->Sections) {
+        ScriptSections.push_back(&IS);
+        Sections.push_back(IS);
+      }
+
+  if ((Flags & SHF_LINK_ORDER)) {
+    std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
+    for (int I = 0, N = Sections.size(); I < N; ++I)
+      *ScriptSections[I] = Sections[I];
+
+    // 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,
+    // all InputSections in the OutputSection have the same dependency.
+    if (auto *D = Sections.front()->getLinkOrderDep())
+      Link = D->getParent()->SectionIndex;
+  }
+
+  if (Type == SHT_GROUP) {
+    finalizeShtGroup<ELFT>(this, Sections);
+    return;
+  }
+
+  if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))
+    return;
+
+  InputSection *First = Sections[0];
+  if (isa<SyntheticSection>(First))
+    return;
+
+  Link = InX::SymTab->getParent()->SectionIndex;
+  // sh_info for SHT_REL[A] sections should contain the section header index of
+  // the section to which the relocation applies.
+  InputSectionBase *S = First->getRelocatedSection();
+  Info = S->getOutputSection()->SectionIndex;
+  Flags |= SHF_INFO_LINK;
+}
+
+// Returns true if S matches /Filename.?\.o$/.
+static bool isCrtBeginEnd(StringRef S, StringRef Filename) {
+  if (!S.endswith(".o"))
+    return false;
+  S = S.drop_back(2);
+  if (S.endswith(Filename))
+    return true;
+  return !S.empty() && S.drop_back().endswith(Filename);
+}
+
+static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }
+static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
+
+// .ctors and .dtors are sorted by this priority from highest to lowest.
+//
+//  1. The section was contained in crtbegin (crtbegin contains
+//     some sentinel value in its .ctors and .dtors so that the runtime
+//     can find the beginning of the sections.)
+//
+//  2. The section has an optional priority value in the form of ".ctors.N"
+//     or ".dtors.N" where N is a number. Unlike .{init,fini}_array,
+//     they are compared as string rather than number.
+//
+//  3. The section is just ".ctors" or ".dtors".
+//
+//  4. The section was contained in crtend, which contains an end marker.
+//
+// In an ideal world, we don't need this function because .init_array and
+// .ctors are duplicate features (and .init_array is newer.) However, there
+// are too many real-world use cases of .ctors, so we had no choice to
+// support that with this rather ad-hoc semantics.
+static bool compCtors(const InputSection *A, const InputSection *B) {
+  bool BeginA = isCrtbegin(A->File->getName());
+  bool BeginB = isCrtbegin(B->File->getName());
+  if (BeginA != BeginB)
+    return BeginA;
+  bool EndA = isCrtend(A->File->getName());
+  bool EndB = isCrtend(B->File->getName());
+  if (EndA != EndB)
+    return EndB;
+  StringRef X = A->Name;
+  StringRef Y = B->Name;
+  assert(X.startswith(".ctors") || X.startswith(".dtors"));
+  assert(Y.startswith(".ctors") || Y.startswith(".dtors"));
+  X = X.substr(6);
+  Y = Y.substr(6);
+  if (X.empty() && Y.empty())
+    return false;
+  return X < Y;
+}
+
+// Sorts input sections by the special rules for .ctors and .dtors.
+// Unfortunately, the rules are different from the one for .{init,fini}_array.
+// Read the comment above.
+void OutputSection::sortCtorsDtors() {
+  assert(Commands.size() == 1);
+  auto *ISD = cast<InputSectionDescription>(Commands[0]);
+  std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors);
+}
+
+// If an input string is in the form of "foo.N" where N is a number,
+// return N. Otherwise, returns 65536, which is one greater than the
+// lowest priority.
+int elf::getPriority(StringRef S) {
+  size_t Pos = S.rfind('.');
+  if (Pos == StringRef::npos)
+    return 65536;
+  int V;
+  if (!to_integer(S.substr(Pos + 1), V, 10))
+    return 65536;
+  return V;
+}
+
+// Sorts input sections by section name suffixes, so that .foo.N comes
+// before .foo.M if N < M. Used to sort .{init,fini}_array.N sections.
+// We want to keep the original order if the priorities are the same
+// because the compiler keeps the original initialization order in a
+// translation unit and we need to respect that.
+// For more detail, read the section of the GCC's manual about init_priority.
+void OutputSection::sortInitFini() {
+  // Sort sections by priority.
+  sort([](InputSectionBase *S) { return getPriority(S->Name); });
+}
+
+uint32_t OutputSection::getFiller() {
+  if (Filler)
+    return *Filler;
+  if (Flags & SHF_EXECINSTR)
+    return Target->TrapInstr;
+  return 0;
+}
+
 template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr);
 template void OutputSection::writeHeaderTo<ELF32BE>(ELF32BE::Shdr *Shdr);
 template void OutputSection::writeHeaderTo<ELF64LE>(ELF64LE::Shdr *Shdr);
 template void OutputSection::writeHeaderTo<ELF64BE>(ELF64BE::Shdr *Shdr);
+
+template void OutputSection::writeTo<ELF32LE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF32BE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF64LE>(uint8_t *Buf);
+template void OutputSection::writeTo<ELF64BE>(uint8_t *Buf);
+
+template void OutputSection::maybeCompress<ELF32LE>();
+template void OutputSection::maybeCompress<ELF32BE>();
+template void OutputSection::maybeCompress<ELF64LE>();
+template void OutputSection::maybeCompress<ELF64BE>();
+
+template void OutputSection::finalize<ELF32LE>();
+template void OutputSection::finalize<ELF32BE>();
+template void OutputSection::finalize<ELF64LE>();
+template void OutputSection::finalize<ELF64BE>();

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Thu Jul 27 12:22:43 2017
@@ -12,6 +12,7 @@
 
 #include "Config.h"
 #include "InputSection.h"
+#include "LinkerScript.h"
 #include "Relocations.h"
 
 #include "lld/Core/LLVM.h"
@@ -38,13 +39,14 @@ class DefinedRegular;
 // It is composed of multiple InputSections.
 // The writer creates multiple OutputSections and assign them unique,
 // non-overlapping file offsets and VAs.
-class OutputSection final : public SectionBase {
+class OutputSection final : public BaseCommand, public SectionBase {
 public:
   OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);
 
   static bool classof(const SectionBase *S) {
     return S->kind() == SectionBase::Output;
   }
+  static bool classof(const BaseCommand *C);
 
   uint64_t getLMA() const { return Addr + LMAOffset; }
   template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
@@ -80,7 +82,6 @@ public:
   uint32_t ShName = 0;
 
   void addSection(InputSection *S);
-  std::vector<InputSection *> Sections;
 
   // Used for implementation of --compress-debug-sections option.
   std::vector<uint8_t> ZDebugHeader;
@@ -88,8 +89,33 @@ public:
 
   // Location in the output buffer.
   uint8_t *Loc = nullptr;
+
+  // The following members are normally only used in linker scripts.
+  MemoryRegion *MemRegion = nullptr;
+  Expr AddrExpr;
+  Expr AlignExpr;
+  Expr LMAExpr;
+  Expr SubalignExpr;
+  std::vector<BaseCommand *> Commands;
+  std::vector<StringRef> Phdrs;
+  llvm::Optional<uint32_t> Filler;
+  ConstraintKind Constraint = ConstraintKind::NoConstraint;
+  std::string Location;
+  std::string MemoryRegionName;
+  bool Noload = false;
+
+  template <class ELFT> void finalize();
+  template <class ELFT> void writeTo(uint8_t *Buf);
+  template <class ELFT> void maybeCompress();
+  uint32_t getFiller();
+
+  void sort(std::function<int(InputSectionBase *S)> Order);
+  void sortInitFini();
+  void sortCtorsDtors();
 };
 
+int getPriority(StringRef S);
+
 // All output sections that are handled by the linker specially are
 // globally accessible. Writer initializes them, so don't use them
 // until Writer is initialized.
@@ -146,7 +172,6 @@ uint64_t getHeaderSize();
 void reportDiscarded(InputSectionBase *IS);
 
 extern std::vector<OutputSection *> OutputSections;
-extern std::vector<OutputSectionCommand *> OutputSectionCommands;
 } // namespace elf
 } // namespace lld
 

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Thu Jul 27 12:22:43 2017
@@ -1006,7 +1006,7 @@ void ThunkCreator::mergeThunks() {
   }
 }
 
-static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) {
+static uint32_t findEndOfFirstNonExec(OutputSection &Cmd) {
   for (BaseCommand *Base : Cmd.Commands)
     if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
       for (auto *IS : ISD->Sections)
@@ -1015,11 +1015,11 @@ static uint32_t findEndOfFirstNonExec(Ou
   return 0;
 }
 
-ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd,
+ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *Cmd,
                                           std::vector<InputSection *> *ISR) {
   if (CurTS == nullptr) {
     uint32_t Off = findEndOfFirstNonExec(*Cmd);
-    CurTS = addThunkSection(Cmd->Sec, ISR, Off);
+    CurTS = addThunkSection(Cmd, ISR, Off);
   }
   return CurTS;
 }
@@ -1028,10 +1028,9 @@ ThunkSection *ThunkCreator::getISThunkSe
   ThunkSection *TS = ThunkedSections.lookup(IS);
   if (TS)
     return TS;
-  auto *TOS = IS->getParent();
 
   // Find InputSectionRange within TOS that IS is in
-  OutputSectionCommand *C = Script->getCmd(TOS);
+  OutputSection *C = IS->getParent();
   std::vector<InputSection *> *Range = nullptr;
   for (BaseCommand *BC : C->Commands)
     if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
@@ -1043,15 +1042,15 @@ ThunkSection *ThunkCreator::getISThunkSe
         break;
       }
     }
-  TS = addThunkSection(TOS, Range, IS->OutSecOff);
+  TS = addThunkSection(C, Range, IS->OutSecOff);
   ThunkedSections[IS] = TS;
   return TS;
 }
 
-ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
+ThunkSection *ThunkCreator::addThunkSection(OutputSection *Cmd,
                                             std::vector<InputSection *> *ISR,
                                             uint64_t Off) {
-  auto *TS = make<ThunkSection>(OS, Off);
+  auto *TS = make<ThunkSection>(Cmd, Off);
   ThunkSections[ISR].push_back(TS);
   return TS;
 }
@@ -1074,19 +1073,18 @@ std::pair<Thunk *, bool> ThunkCreator::g
 // Call Fn on every executable InputSection accessed via the linker script
 // InputSectionDescription::Sections.
 void ThunkCreator::forEachExecInputSection(
-    ArrayRef<OutputSectionCommand *> OutputSections,
-    std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
+    ArrayRef<OutputSection *> OutputSections,
+    std::function<void(OutputSection *, std::vector<InputSection *> *,
                        InputSection *)>
         Fn) {
-  for (OutputSectionCommand *Cmd : OutputSections) {
-    OutputSection *OS = Cmd->Sec;
+  for (OutputSection *OS : OutputSections) {
     if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
       continue;
-    for (BaseCommand *BC : Cmd->Commands)
+    for (BaseCommand *BC : OS->Commands)
       if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
         CurTS = nullptr;
         for (InputSection *IS : ISD->Sections)
-          Fn(Cmd, &ISD->Sections, IS);
+          Fn(OS, &ISD->Sections, IS);
       }
   }
 }
@@ -1101,8 +1099,7 @@ void ThunkCreator::forEachExecInputSecti
 //
 // FIXME: All Thunks are assumed to be in range of the relocation. Range
 // extension Thunks are not yet supported.
-bool ThunkCreator::createThunks(
-    ArrayRef<OutputSectionCommand *> OutputSections) {
+bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
   if (Pass > 0)
     ThunkSections.clear();
 
@@ -1112,7 +1109,7 @@ bool ThunkCreator::createThunks(
   // We separate the creation of ThunkSections from the insertion of the
   // ThunkSections back into the OutputSection as ThunkSections are not always
   // inserted into the same OutputSection as the caller.
-  forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd,
+  forEachExecInputSection(OutputSections, [&](OutputSection *Cmd,
                                               std::vector<InputSection *> *ISR,
                                               InputSection *IS) {
     for (Relocation &Rel : IS->Relocations) {
@@ -1127,7 +1124,7 @@ bool ThunkCreator::createThunks(
         // Find or create a ThunkSection for the new Thunk
         ThunkSection *TS;
         if (auto *TIS = T->getTargetInputSection())
-          TS = getISThunkSec(TIS, Cmd->Sec);
+          TS = getISThunkSec(TIS, Cmd);
         else
           TS = getOSThunkSec(Cmd, ISR);
         TS->addThunk(T);

Modified: lld/trunk/ELF/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.h (original)
+++ lld/trunk/ELF/Relocations.h Thu Jul 27 12:22:43 2017
@@ -21,7 +21,7 @@ class SymbolBody;
 class InputSection;
 class InputSectionBase;
 class OutputSection;
-struct OutputSectionCommand;
+class OutputSection;
 
 // List of target-independent relocation types. Relocations read
 // from files are converted to these types so that the main code
@@ -125,7 +125,7 @@ class Thunk;
 class ThunkCreator {
 public:
   // Return true if Thunks have been added to OutputSections
-  bool createThunks(ArrayRef<OutputSectionCommand *> OutputSections);
+  bool createThunks(ArrayRef<OutputSection *> OutputSections);
 
   // The number of completed passes of createThunks this permits us
   // to do one time initialization on Pass 0 and put a limit on the
@@ -134,16 +134,16 @@ public:
 
 private:
   void mergeThunks();
-  ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd,
+  ThunkSection *getOSThunkSec(OutputSection *Cmd,
                               std::vector<InputSection *> *ISR);
   ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
   void forEachExecInputSection(
-      ArrayRef<OutputSectionCommand *> OutputSections,
-      std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
+      ArrayRef<OutputSection *> OutputSections,
+      std::function<void(OutputSection *, std::vector<InputSection *> *,
                          InputSection *)>
           Fn);
   std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
-  ThunkSection *addThunkSection(OutputSection *OS,
+  ThunkSection *addThunkSection(OutputSection *Cmd,
                                 std::vector<InputSection *> *, uint64_t Off);
   // Record all the available Thunks for a Symbol
   llvm::DenseMap<SymbolBody *, std::vector<Thunk *>> ThunkedSymbols;

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Thu Jul 27 12:22:43 2017
@@ -55,7 +55,7 @@ public:
 
 private:
   void addFile(StringRef Path);
-  OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation);
+  OutputSection *checkSection(OutputSection *Cmd, StringRef Loccation);
 
   void readAsNeeded();
   void readEntry();
@@ -76,8 +76,8 @@ private:
   BytesDataCommand *readBytesDataCommand(StringRef Tok);
   uint32_t readFill();
   uint32_t parseFill(StringRef Tok);
-  void readSectionAddressType(OutputSectionCommand *Cmd);
-  OutputSectionCommand *readOutputSectionDescription(StringRef OutSec);
+  void readSectionAddressType(OutputSection *Cmd);
+  OutputSection *readOutputSectionDescription(StringRef OutSec);
   std::vector<StringRef> readOutputSectionPhdrs();
   InputSectionDescription *readInputSectionDescription(StringRef Tok);
   StringMatcher readFilePatterns();
@@ -581,7 +581,7 @@ uint32_t ScriptParser::readFill() {
 //
 // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
 // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
-void ScriptParser::readSectionAddressType(OutputSectionCommand *Cmd) {
+void ScriptParser::readSectionAddressType(OutputSection *Cmd) {
   if (consume("(")) {
     if (consume("NOLOAD")) {
       expect(")");
@@ -601,10 +601,9 @@ void ScriptParser::readSectionAddressTyp
   }
 }
 
-OutputSectionCommand *
-ScriptParser::readOutputSectionDescription(StringRef OutSec) {
-  OutputSectionCommand *Cmd =
-      Script->createOutputSectionCommand(OutSec, getCurrentLocation());
+OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
+  OutputSection *Cmd =
+      Script->createOutputSection(OutSec, getCurrentLocation());
 
   if (peek() != ":")
     readSectionAddressType(Cmd);
@@ -857,14 +856,11 @@ StringRef ScriptParser::readParenLiteral
   return Tok;
 }
 
-OutputSection *ScriptParser::checkSection(OutputSectionCommand *Cmd,
+OutputSection *ScriptParser::checkSection(OutputSection *Cmd,
                                           StringRef Location) {
   if (Cmd->Location.empty() && Script->ErrorOnMissingSection)
     error(Location + ": undefined section " + Cmd->Name);
-  if (Cmd->Sec)
-    return Cmd->Sec;
-  static OutputSection Dummy("", 0, 0);
-  return &Dummy;
+  return Cmd;
 }
 
 Expr ScriptParser::readPrimary() {
@@ -895,7 +891,7 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "ADDR") {
     StringRef Name = readParenLiteral();
-    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
     return [=]() -> ExprValue {
       return {checkSection(Cmd, Location), 0, Location};
     };
@@ -916,7 +912,7 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "ALIGNOF") {
     StringRef Name = readParenLiteral();
-    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
     return [=] { return checkSection(Cmd, Location)->Alignment; };
   }
   if (Tok == "ASSERT")
@@ -962,7 +958,7 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "LOADADDR") {
     StringRef Name = readParenLiteral();
-    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
     return [=] { return checkSection(Cmd, Location)->getLMA(); };
   }
   if (Tok == "ORIGIN") {
@@ -981,11 +977,11 @@ Expr ScriptParser::readPrimary() {
   }
   if (Tok == "SIZEOF") {
     StringRef Name = readParenLiteral();
-    OutputSectionCommand *Cmd = Script->getOrCreateOutputSectionCommand(Name);
+    OutputSection *Cmd = Script->getOrCreateOutputSection(Name);
     // Linker script does not create an output section if its content is empty.
     // We want to allow SIZEOF(.foo) where .foo is a section which happened to
     // be empty.
-    return [=] { return Cmd->Sec ? Cmd->Sec->Size : 0; };
+    return [=] { return Cmd->Size; };
   }
   if (Tok == "SIZEOF_HEADERS")
     return [=] { return elf::getHeaderSize(); };

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Thu Jul 27 12:22:43 2017
@@ -2282,7 +2282,7 @@ void ARMExidxSentinelSection::writeTo(ui
   // sentinel last. We need to find the InputSection that precedes the
   // sentinel. By construction the Sentinel is in the last
   // InputSectionDescription as the InputSection that precedes it.
-  OutputSectionCommand *C = Script->getCmd(getParent());
+  OutputSection *C = getParent();
   auto ISD = std::find_if(C->Commands.rbegin(), C->Commands.rend(),
                           [](const BaseCommand *Base) {
                             return isa<InputSectionDescription>(Base);

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=309311&r1=309310&r2=309311&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Jul 27 12:22:43 2017
@@ -46,7 +46,6 @@ public:
   void run();
 
 private:
-  void clearOutputSections();
   void createSyntheticSections();
   void copyLocalSymbols();
   void addSectionSymbols();
@@ -79,8 +78,7 @@ private:
   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 @@ template <class ELFT> static void combin
   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 @@ template <class ELFT> void Writer<ELFT>:
     Script->processCommands(Factory);
     createSections();
   }
-  clearOutputSections();
 
   if (Config->Discard != DiscardPolicy::All)
     copyLocalSymbols();
@@ -210,9 +198,8 @@ template <class ELFT> void Writer<ELFT>:
   // 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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
     return;
 
   // Handle -Map option.
-  writeMapFile<ELFT>(OutputSectionCommands);
+  writeMapFile<ELFT>();
   if (ErrorCount)
     return;
 
@@ -496,15 +483,15 @@ template <class ELFT> void Writer<ELFT>:
   // 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 unsigned getSectionRank(const Out
 }
 
 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 @@ template <class ELFT> void Writer<ELFT>:
 
 // 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 @@ template <class ELFT> static void sortBy
 
   // 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 @@ void Writer<ELFT>::forEachRelSec(std::fu
 }
 
 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 @@ static int getRankProximity(OutputSectio
 //  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 @@ template <typename ELFT>
 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 @@ findOrphanPos(std::vector<BaseCommand *>
   // 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 @@ template <class ELFT> void Writer<ELFT>:
     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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
 
   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 @@ static void removeUnusedSyntheticSection
     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 @@ static void removeUnusedSyntheticSection
           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 @@ static void removeUnusedSyntheticSection
 
 // 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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
     // 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 @@ template <class ELFT> void Writer<ELFT>:
   // 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>:
 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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ void Writer<ELFT>::addStartStopSymbols(O
   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 @@ template <class ELFT> std::vector<PhdrEn
   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 @@ template <class ELFT> std::vector<PhdrEn
   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 @@ template <class ELFT> std::vector<PhdrEn
     // 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 @@ template <class ELFT> std::vector<PhdrEn
 
   // 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 @@ template <class ELFT> std::vector<PhdrEn
   // 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 @@ template <class ELFT> std::vector<PhdrEn
 
   // 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 @@ template <class ELFT> std::vector<PhdrEn
 
   // 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 @@ template <class ELFT>
 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 @@ void Writer<ELFT>::addPtArmExid(std::vec
 // 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 @@ template <class ELFT> void Writer<ELFT>:
       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 @@ template <class ELFT> void Writer<ELFT>:
 // 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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> uint64_t Writer<EL
     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 @@ template <class ELFT> void Writer<ELFT>:
       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 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   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 @@ template <class ELFT> void Writer<ELFT>:
   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 @@ template <class ELFT> void Writer<ELFT>:
 
   // 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>:
 
 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 @@ template <class ELFT> void Writer<ELFT>:
 
   // 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 @@ template <class ELFT> void Writer<ELFT>:
   // 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() {




More information about the llvm-commits mailing list