[lld] r361925 - ELF: Add basic partition data structures and behaviours.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Tue May 28 20:55:20 PDT 2019


Author: pcc
Date: Tue May 28 20:55:20 2019
New Revision: 361925

URL: http://llvm.org/viewvc/llvm-project?rev=361925&view=rev
Log:
ELF: Add basic partition data structures and behaviours.

This change causes us to read partition specifications from partition
specification sections and split output sections into partitions according
to their reachability from partition entry points.

This is only the first step towards a full implementation of partitions. Later
changes will add additional synthetic sections to each partition so that
they can be loaded independently.

Differential Revision: https://reviews.llvm.org/D60353

Added:
    lld/trunk/test/ELF/partition-errors.s
    lld/trunk/test/ELF/partition-icf.s
    lld/trunk/test/ELF/partition-move-to-main.s
    lld/trunk/test/ELF/partitions.s
Modified:
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/ICF.cpp
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/MapFile.cpp
    lld/trunk/ELF/MarkLive.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/Symbols.h
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue May 28 20:55:20 2019
@@ -98,6 +98,8 @@ bool elf::link(ArrayRef<const char *> Ar
   Tar = nullptr;
   memset(&In, 0, sizeof(In));
 
+  Partitions = {Partition()};
+
   SharedFile::VernauxNum = 0;
 
   Config->ProgName = Args[0];
@@ -1344,7 +1346,7 @@ static void replaceCommonSymbols() {
 
     auto *Bss = make<BssSection>("COMMON", S->Size, S->Alignment);
     Bss->File = S->File;
-    Bss->Live = !Config->GcSections;
+    Bss->markDead();
     InputSections.push_back(Bss);
     S->replace(Defined{S->File, S->getName(), S->Binding, S->StOther, S->Type,
                        /*Value=*/0, S->Size, Bss});
@@ -1432,6 +1434,55 @@ static void findKeepUniqueSections(opt::
   }
 }
 
+// This function reads a symbol partition specification section. These sections
+// are used to control which partition a symbol is allocated to. See
+// https://lld.llvm.org/Partitions.html for more details on partitions.
+template <typename ELFT>
+static void readSymbolPartitionSection(InputSectionBase *S) {
+  // Read the relocation that refers to the partition's entry point symbol.
+  Symbol *Sym;
+  if (S->AreRelocsRela)
+    Sym = &S->getFile<ELFT>()->getRelocTargetSym(S->template relas<ELFT>()[0]);
+  else
+    Sym = &S->getFile<ELFT>()->getRelocTargetSym(S->template rels<ELFT>()[0]);
+  if (!isa<Defined>(Sym) || !Sym->includeInDynsym())
+    return;
+
+  StringRef PartName = reinterpret_cast<const char *>(S->data().data());
+  for (Partition &Part : Partitions) {
+    if (Part.Name == PartName) {
+      Sym->Partition = Part.getNumber();
+      return;
+    }
+  }
+
+  // Forbid partitions from being used on incompatible targets, and forbid them
+  // from being used together with various linker features that assume a single
+  // set of output sections.
+  if (Script->HasSectionsCommand)
+    error(toString(S->File) +
+          ": partitions cannot be used with the SECTIONS command");
+  if (Script->hasPhdrsCommands())
+    error(toString(S->File) +
+          ": partitions cannot be used with the PHDRS command");
+  if (!Config->SectionStartMap.empty())
+    error(toString(S->File) + ": partitions cannot be used with "
+                              "--section-start, -Ttext, -Tdata or -Tbss");
+  if (Config->EMachine == EM_MIPS)
+    error(toString(S->File) + ": partitions cannot be used on this target");
+
+  // Impose a limit of no more than 254 partitions. This limit comes from the
+  // sizes of the Partition fields in InputSectionBase and Symbol, as well as
+  // the amount of space devoted to the partition number in RankFlags.
+  if (Partitions.size() == 254)
+    fatal("may not have more than 254 partitions");
+
+  Partitions.emplace_back();
+  Partition &NewPart = Partitions.back();
+  NewPart.Name = PartName;
+  Sym->Partition = NewPart.getNumber();
+}
+
 template <class ELFT> static Symbol *addUndefined(StringRef Name) {
   return Symtab->addSymbol(
       Undefined{nullptr, Name, STB_GLOBAL, STV_DEFAULT, 0});
@@ -1700,13 +1751,17 @@ template <class ELFT> void LinkerDriver:
     for (InputSectionBase *S : F->getSections())
       InputSections.push_back(cast<InputSection>(S));
 
-  // We do not want to emit debug sections if --strip-all
-  // or -strip-debug are given.
-  if (Config->Strip != StripPolicy::None) {
-    llvm::erase_if(InputSections, [](InputSectionBase *S) {
-      return S->Name.startswith(".debug") || S->Name.startswith(".zdebug");
-    });
-  }
+  llvm::erase_if(InputSections, [](InputSectionBase *S) {
+    if (S->Type == SHT_LLVM_SYMPART) {
+      readSymbolPartitionSection<ELFT>(S);
+      return true;
+    }
+
+    // We do not want to emit debug sections if --strip-all
+    // or -strip-debug are given.
+    return Config->Strip != StripPolicy::None &&
+           (S->Name.startswith(".debug") || S->Name.startswith(".zdebug"));
+  });
 
   Config->EFlags = Target->calcEFlags();
   // MaxPageSize (sometimes called abi page size) is the maximum page size that

Modified: lld/trunk/ELF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ICF.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/ICF.cpp (original)
+++ lld/trunk/ELF/ICF.cpp Tue May 28 20:55:20 2019
@@ -157,7 +157,7 @@ private:
 
 // Returns true if section S is subject of ICF.
 static bool isEligible(InputSection *S) {
-  if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC))
+  if (!S->isLive() || S->KeepUnique || !(S->Flags & SHF_ALLOC))
     return false;
 
   // Don't merge writable sections. .data.rel.ro sections are marked as writable
@@ -496,7 +496,7 @@ template <class ELFT> void ICF<ELFT>::ru
       // we want to remove duplicate implicit dependencies such as link order
       // and relocation sections.
       for (InputSection *IS : Sections[I]->DependentSections)
-        IS->Live = false;
+        IS->markDead();
     }
   });
 }

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Tue May 28 20:55:20 2019
@@ -443,7 +443,7 @@ void InputSection::copyRelocations(uint8
         continue;
       }
       SectionBase *Section = D->Section->Repl;
-      if (!Section->Live) {
+      if (!Section->isLive()) {
         P->setSymbolAndType(0, 0, false);
         continue;
       }
@@ -1095,8 +1095,19 @@ template <class ELFT> void InputSection:
 
 void InputSection::replace(InputSection *Other) {
   Alignment = std::max(Alignment, Other->Alignment);
+
+  // When a section is replaced with another section that was allocated to
+  // another partition, the replacement section (and its associated sections)
+  // need to be placed in the main partition so that both partitions will be
+  // able to access it.
+  if (Partition != Other->Partition) {
+    Partition = 1;
+    for (InputSection *IS : DependentSections)
+      IS->Partition = 1;
+  }
+
   Other->Repl = Repl;
-  Other->Live = false;
+  Other->markDead();
 }
 
 template <class ELFT>

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Tue May 28 20:55:20 2019
@@ -54,10 +54,6 @@ public:
   // The next three bit fields are only used by InputSectionBase, but we
   // put them here so the struct packs better.
 
-  // The garbage collector sets sections' Live bits.
-  // If GC is disabled, all sections are considered live by default.
-  unsigned Live : 1;
-
   // True if this section has already been placed to a linker script
   // output section. This is needed because, in a linker script, you
   // can refer to the same section more than once. For example, in
@@ -76,6 +72,11 @@ public:
   // Set for sections that should not be folded by ICF.
   unsigned KeepUnique : 1;
 
+  // The 1-indexed partition that this section is assigned to by the garbage
+  // collector, or 0 if this section is dead. Normally there is only one
+  // partition, so this will either be 0 or 1.
+  uint8_t Partition;
+
   // These corresponds to the fields in Elf_Shdr.
   uint32_t Alignment;
   uint64_t Flags;
@@ -95,12 +96,16 @@ public:
 
   uint64_t getVA(uint64_t Offset = 0) const;
 
+  bool isLive() const { return Partition != 0; }
+  void markLive() { Partition = 1; }
+  void markDead() { Partition = 0; }
+
 protected:
   SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,
               uint64_t Entsize, uint64_t Alignment, uint32_t Type,
               uint32_t Info, uint32_t Link)
-      : Name(Name), Repl(this), SectionKind(SectionKind), Live(false),
-        Assigned(false), Bss(false), KeepUnique(false), Alignment(Alignment),
+      : Name(Name), Repl(this), SectionKind(SectionKind), Assigned(false),
+        Bss(false), KeepUnique(false), Partition(0), Alignment(Alignment),
         Flags(Flags), Entsize(Entsize), Type(Type), Link(Link), Info(Info) {}
 };
 

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue May 28 20:55:20 2019
@@ -380,7 +380,7 @@ LinkerScript::computeInputSections(const
     size_t SizeBefore = Ret.size();
 
     for (InputSectionBase *Sec : InputSections) {
-      if (!Sec->Live || Sec->Assigned)
+      if (!Sec->isLive() || Sec->Assigned)
         continue;
 
       // For -emit-relocs we have to ignore entries like
@@ -425,7 +425,7 @@ void LinkerScript::discard(ArrayRef<Inpu
       In.HashTab = nullptr;
 
     S->Assigned = false;
-    S->Live = false;
+    S->markDead();
     discard(S->DependentSections);
   }
 }
@@ -544,8 +544,9 @@ static OutputSection *createSection(Inpu
   return Sec;
 }
 
-static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
-                                  InputSectionBase *IS, StringRef OutsecName) {
+static OutputSection *
+addInputSec(StringMap<TinyPtrVector<OutputSection *>> &Map,
+            InputSectionBase *IS, StringRef OutsecName) {
   // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
   // option is given. A section with SHT_GROUP defines a "section group", and
   // its members have SHF_GROUP attribute. Usually these flags have already been
@@ -624,23 +625,26 @@ static OutputSection *addInputSec(String
   //
   // Given the above issues, we instead merge sections by name and error on
   // incompatible types and flags.
-  OutputSection *&Sec = Map[OutsecName];
-  if (Sec) {
+  TinyPtrVector<OutputSection *> &V = Map[OutsecName];
+  for (OutputSection *Sec : V) {
+    if (Sec->Partition != IS->Partition)
+      continue;
     Sec->addSection(cast<InputSection>(IS));
     return nullptr;
   }
 
-  Sec = createSection(IS, OutsecName);
+  OutputSection *Sec = createSection(IS, OutsecName);
+  V.push_back(Sec);
   return Sec;
 }
 
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections() {
-  StringMap<OutputSection *> Map;
+  StringMap<TinyPtrVector<OutputSection *>> Map;
   std::vector<OutputSection *> V;
 
   auto Add = [&](InputSectionBase *S) {
-    if (!S->Live || S->Parent)
+    if (!S->isLive() || S->Parent)
       return;
 
     StringRef Name = getOutputSectionName(S);
@@ -886,7 +890,7 @@ void LinkerScript::adjustSectionsBeforeS
     // A live output section means that some input section was added to it. It
     // might have been removed (if it was empty synthetic section), but we at
     // least know the flags.
-    if (Sec->Live)
+    if (Sec->isLive())
       Flags = Sec->Flags;
 
     // We do not want to keep any special flags for output section
@@ -897,7 +901,7 @@ void LinkerScript::adjustSectionsBeforeS
                             SHF_WRITE | SHF_EXECINSTR);
 
     if (IsEmpty && isDiscardable(*Sec)) {
-      Sec->Live = false;
+      Sec->markDead();
       Cmd = nullptr;
     }
   }

Modified: lld/trunk/ELF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MapFile.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/MapFile.cpp (original)
+++ lld/trunk/ELF/MapFile.cpp Tue May 28 20:55:20 2019
@@ -57,7 +57,7 @@ static std::vector<Defined *> getSymbols
   for (InputFile *File : ObjectFiles)
     for (Symbol *B : File->getSymbols())
       if (auto *DR = dyn_cast<Defined>(B))
-        if (!DR->isSection() && DR->Section && DR->Section->Live &&
+        if (!DR->isSection() && DR->Section && DR->Section->isLive() &&
             (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))
           V.push_back(DR);
   return V;
@@ -239,7 +239,7 @@ void elf::writeCrossReferenceTable() {
       if (isa<SharedSymbol>(Sym))
         Map[Sym].insert(File);
       if (auto *D = dyn_cast<Defined>(Sym))
-        if (!D->isLocal() && (!D->Section || D->Section->Live))
+        if (!D->isLocal() && (!D->Section || D->Section->isLive()))
           Map[D].insert(File);
     }
   }

Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Tue May 28 20:55:20 2019
@@ -25,6 +25,7 @@
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "SyntheticSections.h"
 #include "Target.h"
 #include "lld/Common/Memory.h"
 #include "lld/Common/Strings.h"
@@ -44,11 +45,15 @@ using namespace lld::elf;
 namespace {
 template <class ELFT> class MarkLive {
 public:
+  MarkLive(unsigned Partition) : Partition(Partition) {}
+
   void run();
+  void moveToMain();
 
 private:
   void enqueue(InputSectionBase *Sec, uint64_t Offset);
   void markSymbol(Symbol *Sym);
+  void mark();
 
   template <class RelTy>
   void resolveReloc(InputSectionBase &Sec, RelTy &Rel, bool IsLSDA);
@@ -56,6 +61,9 @@ private:
   template <class RelTy>
   void scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels);
 
+  // The index of the partition that we are currently processing.
+  unsigned Partition;
+
   // A list of sections to visit.
   SmallVector<InputSection *, 256> Queue;
 
@@ -183,9 +191,12 @@ void MarkLive<ELFT>::enqueue(InputSectio
   if (auto *MS = dyn_cast<MergeInputSection>(Sec))
     MS->getSectionPiece(Offset)->Live = true;
 
-  if (Sec->Live)
+  // Set Sec->Partition to the meet (i.e. the "minimum") of Partition and
+  // Sec->Partition in the following lattice: 1 < other < 0. If Sec->Partition
+  // doesn't change, we don't need to do anything.
+  if (Sec->Partition == 1 || Sec->Partition == Partition)
     return;
-  Sec->Live = true;
+  Sec->Partition = Sec->Partition ? 1 : Partition;
 
   // Add input section to the queue.
   if (InputSection *S = dyn_cast<InputSection>(Sec))
@@ -203,6 +214,20 @@ template <class ELFT> void MarkLive<ELFT
 // sections to set their "Live" bits.
 template <class ELFT> void MarkLive<ELFT>::run() {
   // Add GC root symbols.
+
+  // Preserve externally-visible symbols if the symbols defined by this
+  // file can interrupt other ELF file's symbols at runtime.
+  Symtab->forEachSymbol([&](Symbol *Sym) {
+    if (Sym->includeInDynsym() && Sym->Partition == Partition)
+      markSymbol(Sym);
+  });
+
+  // If this isn't the main partition, that's all that we need to preserve.
+  if (Partition != 1) {
+    mark();
+    return;
+  }
+
   markSymbol(Symtab->find(Config->Entry));
   markSymbol(Symtab->find(Config->Init));
   markSymbol(Symtab->find(Config->Fini));
@@ -211,13 +236,6 @@ template <class ELFT> void MarkLive<ELFT
   for (StringRef S : Script->ReferencedSymbols)
     markSymbol(Symtab->find(S));
 
-  // Preserve externally-visible symbols if the symbols defined by this
-  // file can interrupt other ELF file's symbols at runtime.
-  Symtab->forEachSymbol([&](Symbol *Sym) {
-    if (Sym->includeInDynsym())
-      markSymbol(Sym);
-  });
-
   // Preserve special sections and those which are specified in linker
   // script KEEP command.
   for (InputSectionBase *Sec : InputSections) {
@@ -226,7 +244,7 @@ template <class ELFT> void MarkLive<ELFT
     // all of them. We also want to preserve personality routines and LSDA
     // referenced by .eh_frame sections, so we scan them for that here.
     if (auto *EH = dyn_cast<EhInputSection>(Sec)) {
-      EH->Live = true;
+      EH->markLive();
       if (!EH->NumRelocations)
         continue;
 
@@ -247,6 +265,10 @@ template <class ELFT> void MarkLive<ELFT
     }
   }
 
+  mark();
+}
+
+template <class ELFT> void MarkLive<ELFT>::mark() {
   // Mark all reachable sections.
   while (!Queue.empty()) {
     InputSectionBase &Sec = *Queue.pop_back_val();
@@ -264,6 +286,22 @@ template <class ELFT> void MarkLive<ELFT
   }
 }
 
+// Move the sections for some symbols to the main partition, specifically ifuncs
+// (because they can result in an IRELATIVE being added to the main partition's
+// GOT, which means that the ifunc must be available when the main partition is
+// loaded) and TLS symbols (because we only know how to correctly process TLS
+// relocations for the main partition).
+template <class ELFT> void MarkLive<ELFT>::moveToMain() {
+  for (InputFile *File : ObjectFiles)
+    for (Symbol *S : File->getSymbols())
+      if (auto *D = dyn_cast<Defined>(S))
+        if ((D->Type == STT_GNU_IFUNC || D->Type == STT_TLS) && D->Section &&
+            D->Section->isLive())
+          markSymbol(S);
+
+  mark();
+}
+
 // Before calling this function, Live bits are off for all
 // input sections. This function make some or all of them on
 // so that they are emitted to the output file.
@@ -271,7 +309,7 @@ template <class ELFT> void elf::markLive
   // If -gc-sections is not given, no sections are removed.
   if (!Config->GcSections) {
     for (InputSectionBase *Sec : InputSections)
-      Sec->Live = true;
+      Sec->markLive();
 
     // If a DSO defines a symbol referenced in a regular object, it is needed.
     Symtab->forEachSymbol([](Symbol *Sym) {
@@ -309,16 +347,23 @@ template <class ELFT> void elf::markLive
     bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);
 
     if (!IsAlloc && !IsLinkOrder && !IsRel)
-      Sec->Live = true;
+      Sec->markLive();
   }
 
   // Follow the graph to mark all live sections.
-  MarkLive<ELFT>().run();
+  for (unsigned CurPart = 1; CurPart <= Partitions.size(); ++CurPart)
+    MarkLive<ELFT>(CurPart).run();
+
+  // If we have multiple partitions, some sections need to live in the main
+  // partition even if they were allocated to a loadable partition. Move them
+  // there now.
+  if (Partitions.size() != 1)
+    MarkLive<ELFT>(1).moveToMain();
 
   // Report garbage-collected sections.
   if (Config->PrintGcSections)
     for (InputSectionBase *Sec : InputSections)
-      if (!Sec->Live)
+      if (!Sec->isLive())
         message("removing unused section " + toString(Sec));
 }
 

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue May 28 20:55:20 2019
@@ -84,10 +84,10 @@ static bool canMergeToProgbits(unsigned
 }
 
 void OutputSection::addSection(InputSection *IS) {
-  if (!Live) {
+  if (!isLive()) {
     // If IS is the first section to be added to this section,
-    // initialize Type, Entsize and flags from IS.
-    Live = true;
+    // initialize Partition, Type, Entsize and flags from IS.
+    Partition = IS->Partition;
     Type = IS->Type;
     Entsize = IS->Entsize;
     Flags = IS->Flags;
@@ -158,7 +158,7 @@ bool OutputSection::classof(const BaseCo
 }
 
 void OutputSection::sort(llvm::function_ref<int(InputSectionBase *S)> Order) {
-  assert(Live);
+  assert(isLive());
   for (BaseCommand *B : SectionCommands)
     if (auto *ISD = dyn_cast<InputSectionDescription>(B))
       sortByOrder(ISD->Sections, Order);

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue May 28 20:55:20 2019
@@ -79,6 +79,7 @@ Symbol *SymbolTable::insert(StringRef Na
   Sym->ExportDynamic = false;
   Sym->CanInline = true;
   Sym->ScriptDefined = false;
+  Sym->Partition = 1;
   return Sym;
 }
 

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue May 28 20:55:20 2019
@@ -333,7 +333,7 @@ void elf::maybeWarnUnorderableSymbol(con
     Warn(": unable to order absolute symbol: ");
   else if (D && isa<OutputSection>(D->Section))
     Warn(": unable to order synthetic symbol: ");
-  else if (D && !D->Section->Repl->Live)
+  else if (D && !D->Section->Repl->isLive())
     Warn(": unable to order discarded symbol: ");
 }
 

Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue May 28 20:55:20 2019
@@ -255,6 +255,9 @@ public:
   // True if this symbol is defined by a linker script.
   unsigned ScriptDefined : 1;
 
+  // The partition whose dynamic symbol table contains this symbol's definition.
+  uint8_t Partition = 1;
+
   bool isSection() const { return Type == llvm::ELF::STT_SECTION; }
   bool isTls() const { return Type == llvm::ELF::STT_TLS; }
   bool isFunc() const { return Type == llvm::ELF::STT_FUNC; }
@@ -516,6 +519,7 @@ void Symbol::replace(const Symbol &New)
   Traced = Old.Traced;
   IsPreemptible = Old.IsPreemptible;
   ScriptDefined = Old.ScriptDefined;
+  Partition = Old.Partition;
 
   // Symbol length is computed lazily. If we already know a symbol length,
   // propagate it.

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Tue May 28 20:55:20 2019
@@ -107,7 +107,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsS
   for (InputSectionBase *Sec : InputSections) {
     if (Sec->Type != SHT_MIPS_ABIFLAGS)
       continue;
-    Sec->Live = false;
+    Sec->markDead();
     Create = true;
 
     std::string Filename = toString(Sec->File);
@@ -180,7 +180,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSec
 
   Elf_Mips_RegInfo Reginfo = {};
   for (InputSectionBase *Sec : Sections) {
-    Sec->Live = false;
+    Sec->markDead();
 
     std::string Filename = toString(Sec->File);
     ArrayRef<uint8_t> D = Sec->data();
@@ -237,7 +237,7 @@ MipsReginfoSection<ELFT> *MipsReginfoSec
 
   Elf_Mips_RegInfo Reginfo = {};
   for (InputSectionBase *Sec : Sections) {
-    Sec->Live = false;
+    Sec->markDead();
 
     if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) {
       error(toString(Sec->File) + ": invalid size of .reginfo section");
@@ -259,7 +259,7 @@ InputSection *elf::createInterpSection()
 
   auto *Sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, Contents,
                                  ".interp");
-  Sec->Live = true;
+  Sec->markLive();
   return Sec;
 }
 
@@ -358,7 +358,7 @@ bool EhFrameSection::isFdeLive(EhSection
   // FDEs for garbage-collected or merged-by-ICF sections are dead.
   if (auto *D = dyn_cast<Defined>(&B))
     if (SectionBase *Sec = D->Section)
-      return Sec->Live;
+      return Sec->isLive();
   return false;
 }
 
@@ -1290,7 +1290,7 @@ template <class ELFT> void DynamicSectio
   // as RelaIplt have. And we still want to emit proper dynamic tags for that
   // case, so here we always use RelaPlt as marker for the begining of
   // .rel[a].plt section.
-  if (In.RelaPlt->getParent()->Live) {
+  if (In.RelaPlt->getParent()->isLive()) {
     addInSec(DT_JMPREL, In.RelaPlt);
     Entries.push_back({DT_PLTRELSZ, addPltRelSz});
     switch (Config->EMachine) {
@@ -2370,7 +2370,7 @@ readAddressAreas(DWARFContext &Dwarf, In
       if (R.SectionIndex == -1ULL)
         continue;
       InputSectionBase *S = Sections[R.SectionIndex];
-      if (!S || S == &InputSection::Discarded || !S->Live)
+      if (!S || S == &InputSection::Discarded || !S->isLive())
         continue;
       // Range list with zero size has no effect.
       if (R.LowPC == R.HighPC)
@@ -2503,7 +2503,7 @@ template <class ELFT> GdbIndexSection *G
   // a .gdb_index. So we can remove them from the output.
   for (InputSectionBase *S : InputSections)
     if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes")
-      S->Live = false;
+      S->markDead();
 
   std::vector<GdbChunk> Chunks(Sections.size());
   std::vector<std::vector<NameAttrEntry>> NameAttrs(Sections.size());
@@ -2945,7 +2945,7 @@ void elf::mergeSections() {
 
     // We do not want to handle sections that are not alive, so just remove
     // them instead of trying to merge.
-    if (!MS->Live) {
+    if (!MS->isLive()) {
       S = nullptr;
       continue;
     }
@@ -3257,6 +3257,8 @@ bool PPC64LongBranchTargetSection::isNee
 
 InStruct elf::In;
 
+std::vector<Partition> elf::Partitions;
+
 template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
 template GdbIndexSection *GdbIndexSection::create<ELF32BE>();
 template GdbIndexSection *GdbIndexSection::create<ELF64LE>();

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Tue May 28 20:55:20 2019
@@ -31,6 +31,7 @@
 namespace lld {
 namespace elf {
 class Defined;
+struct Partition;
 
 class SyntheticSection : public InputSection {
 public:
@@ -38,7 +39,7 @@ public:
                    StringRef Name)
       : InputSection(nullptr, Flags, Type, Alignment, {}, Name,
                      InputSectionBase::Synthetic) {
-    this->Live = true;
+    markLive();
   }
 
   virtual ~SyntheticSection() = default;
@@ -1062,6 +1063,14 @@ Defined *addSyntheticLocal(StringRef Nam
 
 void addVerneed(Symbol *SS);
 
+extern std::vector<Partition> Partitions;
+
+// Linker generated per-partition sections.
+struct Partition {
+  StringRef Name;
+  unsigned getNumber() const { return this - &Partitions[0] + 1; }
+};
+
 // Linker generated sections which can be used as inputs.
 struct InStruct {
   InputSection *ARMAttributes;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=361925&r1=361924&r2=361925&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue May 28 20:55:20 2019
@@ -157,7 +157,7 @@ template <class ELFT> void Writer<ELFT>:
 
 template <class ELFT> static void combineEhSections() {
   for (InputSectionBase *&S : InputSections) {
-    if (!S->Live)
+    if (!S->isLive())
       continue;
 
     if (auto *ES = dyn_cast<EhInputSection>(S)) {
@@ -607,7 +607,7 @@ static bool includeInSymtab(const Symbol
     Sec = Sec->Repl;
 
     // Exclude symbols pointing to garbage-collected sections.
-    if (isa<InputSectionBase>(Sec) && !Sec->Live)
+    if (isa<InputSectionBase>(Sec) && !Sec->isLive())
       return false;
 
     if (auto *S = dyn_cast<MergeInputSection>(Sec))
@@ -761,8 +761,9 @@ static bool isRelroSection(const OutputS
 // * It is easy to check if a give branch was taken.
 // * It is easy two see how similar two ranks are (see getRankProximity).
 enum RankFlags {
-  RF_NOT_ADDR_SET = 1 << 17,
-  RF_NOT_ALLOC = 1 << 16,
+  RF_NOT_ADDR_SET = 1 << 25,
+  RF_NOT_ALLOC = 1 << 24,
+  RF_PARTITION = 1 << 16, // Partition number (8 bits)
   RF_NOT_INTERP = 1 << 15,
   RF_NOT_NOTE = 1 << 14,
   RF_WRITE = 1 << 13,
@@ -782,7 +783,7 @@ enum RankFlags {
 };
 
 static unsigned getSectionRank(const OutputSection *Sec) {
-  unsigned Rank = 0;
+  unsigned Rank = Sec->Partition * RF_PARTITION;
 
   // We want to put section specified by -T option first, so we
   // can start assigning VA starting from them later.
@@ -953,11 +954,11 @@ void Writer<ELFT>::forEachRelSec(
   // Note that relocations for non-alloc sections are directly
   // processed by InputSection::relocateNonAlloc.
   for (InputSectionBase *IS : InputSections)
-    if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC))
+    if (IS->isLive() && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC))
       Fn(*IS);
   for (EhInputSection *ES : In.EhFrame->Sections)
     Fn(*ES);
-  if (In.ARMExidx && In.ARMExidx->Live)
+  if (In.ARMExidx && In.ARMExidx->isLive())
     for (InputSection *Ex : In.ARMExidx->ExidxSections)
       Fn(*Ex);
 }
@@ -1054,7 +1055,7 @@ static int getRankProximityAux(OutputSec
 
 static int getRankProximity(OutputSection *A, BaseCommand *B) {
   auto *Sec = dyn_cast<OutputSection>(B);
-  return (Sec && Sec->Live) ? getRankProximityAux(A, Sec) : -1;
+  return (Sec && Sec->isLive()) ? getRankProximityAux(A, Sec) : -1;
 }
 
 // When placing orphan sections, we want to place them after symbol assignments
@@ -1096,7 +1097,7 @@ findOrphanPos(std::vector<BaseCommand *>
   int Proximity = getRankProximity(Sec, *I);
   for (; I != E; ++I) {
     auto *CurSec = dyn_cast<OutputSection>(*I);
-    if (!CurSec || !CurSec->Live)
+    if (!CurSec || !CurSec->isLive())
       continue;
     if (getRankProximity(Sec, CurSec) != Proximity ||
         Sec->SortRank < CurSec->SortRank)
@@ -1105,7 +1106,7 @@ findOrphanPos(std::vector<BaseCommand *>
 
   auto IsLiveOutputSec = [](BaseCommand *Cmd) {
     auto *OS = dyn_cast<OutputSection>(Cmd);
-    return OS && OS->Live;
+    return OS && OS->isLive();
   };
   auto J = std::find_if(llvm::make_reverse_iterator(I),
                         llvm::make_reverse_iterator(B), IsLiveOutputSec);

Added: lld/trunk/test/ELF/partition-errors.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/partition-errors.s?rev=361925&view=auto
==============================================================================
--- lld/trunk/test/ELF/partition-errors.s (added)
+++ lld/trunk/test/ELF/partition-errors.s Tue May 28 20:55:20 2019
@@ -0,0 +1,23 @@
+// REQUIRES: x86, mips
+// RUN: llvm-mc -triple=x86_64-unknown-linux -filetype=obj -o %t.o %s
+// RUN: echo "SECTIONS {}" > %t.script
+// RUN: not ld.lld --export-dynamic %t.o %t.script 2>&1 | FileCheck %s
+// RUN: echo "PHDRS { text PT_LOAD; }" > %t2.script
+// RUN: not ld.lld --export-dynamic %t.o %t2.script 2>&1 | FileCheck %s
+// RUN: not ld.lld --export-dynamic %t.o --section-start .text=0 2>&1 | FileCheck %s
+// RUN: not ld.lld --export-dynamic %t.o -Ttext=0 2>&1 | FileCheck %s
+// RUN: not ld.lld --export-dynamic %t.o -Tdata=0 2>&1 | FileCheck %s
+// RUN: not ld.lld --export-dynamic %t.o -Tbss=0 2>&1 | FileCheck %s
+
+// RUN: llvm-mc -triple=mipsel-unknown-linux -filetype=obj -o %t2.o %s
+// RUN: not ld.lld --export-dynamic %t2.o 2>&1 | FileCheck %s
+
+// CHECK: error: {{.*}}.o: partitions cannot be used
+
+.section .llvm_sympart.f1,"", at llvm_sympart
+.asciz "part1"
+.quad f1
+
+.text
+.globl f1
+f1:

Added: lld/trunk/test/ELF/partition-icf.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/partition-icf.s?rev=361925&view=auto
==============================================================================
--- lld/trunk/test/ELF/partition-icf.s (added)
+++ lld/trunk/test/ELF/partition-icf.s Tue May 28 20:55:20 2019
@@ -0,0 +1,50 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
+// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections --icf=all
+// RUN: llvm-readelf -S -s %t | FileCheck %s
+
+// CHECK: [[MAIN:[0-9]+]]] .text
+// CHECK: [[P1:[0-9]+]]] .text
+// CHECK: [[P2:[0-9]+]]] .text
+
+// CHECK: Symbol table '.symtab'
+// CHECK:   [[P1]] f1
+// CHECK:   [[P2]] f2
+// CHECK: [[MAIN]] g1
+// CHECK: [[MAIN]] g2
+
+.section .llvm_sympart.f1,"", at llvm_sympart
+.asciz "part1"
+.quad f1
+
+.section .llvm_sympart.f2,"", at llvm_sympart
+.asciz "part2"
+.quad f2
+
+.section .llvm_sympart.g1,"", at llvm_sympart
+.asciz "part1"
+.quad g1
+
+.section .llvm_sympart.g2,"", at llvm_sympart
+.asciz "part2"
+.quad g2
+
+.section .text.f1,"ax", at progbits
+.globl f1
+f1:
+.byte 1
+
+.section .text.f2,"ax", at progbits
+.globl f2
+f2:
+.byte 2
+
+.section .text.g1,"ax", at progbits
+.globl g1
+g1:
+.byte 3
+
+.section .text.g2,"ax", at progbits
+.globl g2
+g2:
+.byte 3

Added: lld/trunk/test/ELF/partition-move-to-main.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/partition-move-to-main.s?rev=361925&view=auto
==============================================================================
--- lld/trunk/test/ELF/partition-move-to-main.s (added)
+++ lld/trunk/test/ELF/partition-move-to-main.s Tue May 28 20:55:20 2019
@@ -0,0 +1,44 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
+// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
+// RUN: llvm-readelf -S -s %t | FileCheck %s
+
+// Ordinarily, the TLS and IFUNC sections would be split into partitions.
+// Make sure that that didn't happen by checking that there is only one
+// of each section.
+
+// CHECK: .ifunc
+// CHECK: .tdata
+
+// CHECK-NOT: .ifunc
+// CHECK-NOT: .tdata
+
+.section .llvm_sympart.f1,"", at llvm_sympart
+.asciz "part1"
+.quad f1
+
+.section .text._start,"ax", at progbits
+.globl _start
+_start:
+call tls1
+call ifunc1
+
+.section .text.f1,"ax", at progbits
+.globl f1
+f1:
+call tls2
+call ifunc2
+
+.section .ifunc,"ax", at progbits,unique,1
+.type ifunc1 STT_GNU_IFUNC
+ifunc1:
+
+.section .ifunc,"ax", at progbits,unique,2
+.type ifunc2 STT_GNU_IFUNC
+ifunc2:
+
+.section .tdata,"awT", at progbits,unique,1
+tls1:
+
+.section .tdata,"awT", at progbits,unique,2
+tls2:

Added: lld/trunk/test/ELF/partitions.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/partitions.s?rev=361925&view=auto
==============================================================================
--- lld/trunk/test/ELF/partitions.s (added)
+++ lld/trunk/test/ELF/partitions.s Tue May 28 20:55:20 2019
@@ -0,0 +1,63 @@
+// REQUIRES: x86
+// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
+// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
+// RUN: llvm-readelf -S -s %t | FileCheck %s
+
+// This is basically lld/docs/partitions.dot in object file form.
+// Test that the sections are correctly allocated to partitions.
+
+// CHECK: [[MAIN:[0-9]+]]] .text
+// CHECK: [[P1:[0-9]+]]] .text
+// CHECK: [[P2:[0-9]+]]] .text
+
+// CHECK: Symbol table '.symtab'
+// CHECK: [[MAIN]] f3
+// CHECK:   [[P1]] f4
+// CHECK: [[MAIN]] f5
+// CHECK:   [[P2]] f6
+// CHECK: [[MAIN]] _start
+// CHECK:   [[P1]] f1
+// CHECK:   [[P2]] f2
+
+.section .llvm_sympart.f1,"", at llvm_sympart
+.asciz "part1"
+.quad f1
+
+.section .llvm_sympart.f2,"", at llvm_sympart
+.asciz "part2"
+.quad f2
+
+.section .text._start,"ax", at progbits
+.globl _start
+_start:
+call f3
+
+.section .text.f1,"ax", at progbits
+.globl f1
+f1:
+call f3
+call f4
+call f5
+
+.section .text.f2,"ax", at progbits
+.globl f2
+f2:
+call f3
+call f5
+call f6
+
+.section .text.f3,"ax", at progbits
+f3:
+ret
+
+.section .text.f4,"ax", at progbits
+f4:
+ret
+
+.section .text.f5,"ax", at progbits
+f5:
+ret
+
+.section .text.f6,"ax", at progbits
+f6:
+ret




More information about the llvm-commits mailing list