[lld] r294005 - Replace MergeOutputSection with a synthetic section.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 3 05:06:19 PST 2017


Author: rafael
Date: Fri Feb  3 07:06:18 2017
New Revision: 294005

URL: http://llvm.org/viewvc/llvm-project?rev=294005&view=rev
Log:
Replace MergeOutputSection with a synthetic section.

With a synthetic merge section we can have, for example, a single
.rodata section with stings, fixed sized constants and non merge
constants.

I can be simplified further by not setting Entsize, but that is
probably better done is a followup patch.

This should allow some cleanup in the linker script code now that
every output section command maps to just one output section.

Added:
    lld/trunk/test/ELF/linkerscript/merge-sections-syms.s
Modified:
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/SyntheticSections.h
    lld/trunk/ELF/Writer.cpp
    lld/trunk/test/ELF/linkerscript/alternate-sections.s
    lld/trunk/test/ELF/linkerscript/merge-sections.s
    lld/trunk/test/ELF/map-file.s
    lld/trunk/test/ELF/merge-string-align.s
    lld/trunk/test/ELF/no-merge.s

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Fri Feb  3 07:06:18 2017
@@ -80,7 +80,8 @@ InputSectionBase<ELFT>::InputSectionBase
   // If it is not a mergeable section, overwrite the flag so that the flag
   // is consistent with the class. This inconsistency could occur when
   // string merging is disabled using -O0 flag.
-  if (!Config->Relocatable && !isa<MergeInputSection<ELFT>>(this))
+  if (!Config->Relocatable && !isa<MergeInputSection<ELFT>>(this) &&
+      !isa<SyntheticSection<ELFT>>(this))
     this->Flags &= ~(SHF_MERGE | SHF_STRINGS);
 }
 
@@ -118,11 +119,21 @@ typename ELFT::uint InputSectionBase<ELF
     // identify the start of the output .eh_frame.
     return Offset;
   case Merge:
-    return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
+    const MergeInputSection<ELFT> *MS = cast<MergeInputSection<ELFT>>(this);
+    if (MS->MergeSec)
+      return MS->MergeSec->OutSecOff + MS->getOffset(Offset);
+    return MS->getOffset(Offset);
   }
   llvm_unreachable("invalid section kind");
 }
 
+template <class ELFT>
+OutputSectionBase *InputSectionBase<ELFT>::getOutputSection() const {
+  if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(this))
+    return MS->MergeSec ? MS->MergeSec->OutSec : nullptr;
+  return OutSec;
+}
+
 // Uncompress section contents. Note that this function is called
 // from parallel_for_each, so it must be thread-safe.
 template <class ELFT> void InputSectionBase<ELFT>::uncompress() {

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Fri Feb  3 07:06:18 2017
@@ -28,6 +28,7 @@ class SymbolBody;
 struct SectionPiece;
 
 template <class ELFT> class DefinedRegular;
+template <class ELFT> class MergeSyntheticSection;
 template <class ELFT> class ObjectFile;
 template <class ELFT> class OutputSection;
 class OutputSectionBase;
@@ -130,6 +131,8 @@ public:
   // Returns the size of this section (even if this is a common or BSS.)
   size_t getSize() const;
 
+  OutputSectionBase *getOutputSection() const;
+
   ObjectFile<ELFT> *getFile() const { return File; }
   llvm::object::ELFFile<ELFT> getObj() const { return File->getObj(); }
   uintX_t getOffset(const DefinedRegular<ELFT> &Sym) const;
@@ -206,6 +209,11 @@ public:
   SectionPiece *getSectionPiece(uintX_t Offset);
   const SectionPiece *getSectionPiece(uintX_t Offset) const;
 
+  // MergeInputSections are aggregated to a synthetic input sections,
+  // and then added to an OutputSection. This pointer points to a
+  // synthetic MergeSyntheticSection which this section belongs to.
+  MergeSyntheticSection<ELFT> *MergeSec = nullptr;
+
 private:
   void splitStrings(ArrayRef<uint8_t> A, size_t Size);
   void splitNonStrings(ArrayRef<uint8_t> A, size_t Size);

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Fri Feb  3 07:06:18 2017
@@ -479,71 +479,6 @@ template <class ELFT> void EhOutputSecti
 }
 
 template <class ELFT>
-MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t Type,
-                                             uintX_t Flags, uintX_t Alignment)
-    : OutputSectionBase(Name, Type, Flags),
-      Builder(StringTableBuilder::RAW, Alignment) {}
-
-template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
-  Builder.write(Buf);
-}
-
-template <class ELFT>
-void MergeOutputSection<ELFT>::addSection(InputSectionData *C) {
-  auto *Sec = cast<MergeInputSection<ELFT>>(C);
-  Sec->OutSec = this;
-  this->updateAlignment(Sec->Alignment);
-  this->Entsize = Sec->Entsize;
-  Sections.push_back(Sec);
-}
-
-template <class ELFT> bool MergeOutputSection<ELFT>::shouldTailMerge() const {
-  return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2;
-}
-
-template <class ELFT> void MergeOutputSection<ELFT>::finalizeTailMerge() {
-  // Add all string pieces to the string table builder to create section
-  // contents.
-  for (MergeInputSection<ELFT> *Sec : Sections)
-    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
-      if (Sec->Pieces[I].Live)
-        Builder.add(Sec->getData(I));
-
-  // Fix the string table content. After this, the contents will never change.
-  Builder.finalize();
-  this->Size = Builder.getSize();
-
-  // finalize() fixed tail-optimized strings, so we can now get
-  // offsets of strings. Get an offset for each string and save it
-  // to a corresponding StringPiece for easy access.
-  for (MergeInputSection<ELFT> *Sec : Sections)
-    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
-      if (Sec->Pieces[I].Live)
-        Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I));
-}
-
-template <class ELFT> void MergeOutputSection<ELFT>::finalizeNoTailMerge() {
-  // Add all string pieces to the string table builder to create section
-  // contents. Because we are not tail-optimizing, offsets of strings are
-  // fixed when they are added to the builder (string table builder contains
-  // a hash table from strings to offsets).
-  for (MergeInputSection<ELFT> *Sec : Sections)
-    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
-      if (Sec->Pieces[I].Live)
-        Sec->Pieces[I].OutputOff = Builder.add(Sec->getData(I));
-
-  Builder.finalizeInOrder();
-  this->Size = Builder.getSize();
-}
-
-template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
-  if (shouldTailMerge())
-    finalizeTailMerge();
-  else
-    finalizeNoTailMerge();
-}
-
-template <class ELFT>
 static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
   return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED;
 }
@@ -602,24 +537,15 @@ static SectionKey createKey(InputSection
   //
   // Given the above issues, we instead merge sections by name and error on
   // incompatible types and flags.
-  //
-  // The exception being SHF_MERGE, where we create different output sections
-  // for each alignment. This makes each output section simple. In case of
-  // relocatable object generation we do not try to perform merging and treat
-  // SHF_MERGE sections as regular ones, but also create different output
-  // sections for them to allow merging at final linking stage.
-  //
-  // Fortunately, creating symbols in the middle of a merge section is not
-  // supported by bfd or gold, so the SHF_MERGE exception should not cause
-  // problems with most linker scripts.
 
   typedef typename ELFT::uint uintX_t;
-  uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
 
   uintX_t Alignment = 0;
-  if (isa<MergeInputSection<ELFT>>(C) ||
-      (Config->Relocatable && (C->Flags & SHF_MERGE)))
+  uintX_t Flags = 0;
+  if (Config->Relocatable && (C->Flags & SHF_MERGE)) {
     Alignment = std::max<uintX_t>(C->Alignment, C->Entsize);
+    Flags = C->Flags & (SHF_MERGE | SHF_STRINGS);
+  }
 
   return SectionKey{OutsecName, Flags, Alignment};
 }
@@ -674,17 +600,11 @@ OutputSectionFactory<ELFT>::create(const
   }
 
   uint32_t Type = C->Type;
-  switch (C->kind()) {
-  case InputSectionBase<ELFT>::Regular:
-  case InputSectionBase<ELFT>::Synthetic:
-    Sec = make<OutputSection<ELFT>>(Key.Name, Type, Flags);
-    break;
-  case InputSectionBase<ELFT>::EHFrame:
+  if (C->kind() == InputSectionBase<ELFT>::EHFrame)
     return {Out<ELFT>::EhFrame, false};
-  case InputSectionBase<ELFT>::Merge:
-    Sec = make<MergeOutputSection<ELFT>>(Key.Name, Type, Flags, Key.Alignment);
-    break;
-  }
+  Sec = make<OutputSection<ELFT>>(Key.Name, Type, Flags);
+  if (Flags & SHF_MERGE)
+    Sec->Entsize = C->Entsize;
   return {Sec, true};
 }
 
@@ -724,11 +644,6 @@ template class EhOutputSection<ELF32BE>;
 template class EhOutputSection<ELF64LE>;
 template class EhOutputSection<ELF64BE>;
 
-template class MergeOutputSection<ELF32LE>;
-template class MergeOutputSection<ELF32BE>;
-template class MergeOutputSection<ELF64LE>;
-template class MergeOutputSection<ELF64BE>;
-
 template class OutputSectionFactory<ELF32LE>;
 template class OutputSectionFactory<ELF32BE>;
 template class OutputSectionFactory<ELF64LE>;

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Fri Feb  3 07:06:18 2017
@@ -129,30 +129,6 @@ public:
   uint8_t *Loc = nullptr;
 };
 
-template <class ELFT>
-class MergeOutputSection final : public OutputSectionBase {
-  typedef typename ELFT::uint uintX_t;
-
-public:
-  MergeOutputSection(StringRef Name, uint32_t Type, uintX_t Flags,
-                     uintX_t Alignment);
-  void addSection(InputSectionData *S) override;
-  void writeTo(uint8_t *Buf) override;
-  void finalize() override;
-  bool shouldTailMerge() const;
-  Kind getKind() const override { return Merge; }
-  static bool classof(const OutputSectionBase *B) {
-    return B->getKind() == Merge;
-  }
-
-private:
-  void finalizeTailMerge();
-  void finalizeNoTailMerge();
-
-  llvm::StringTableBuilder Builder;
-  std::vector<MergeInputSection<ELFT> *> Sections;
-};
-
 struct CieRecord {
   EhSectionPiece *Piece = nullptr;
   std::vector<EhSectionPiece *> FdePieces;

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Fri Feb  3 07:06:18 2017
@@ -63,7 +63,8 @@ static typename ELFT::uint getSymVA(cons
       Offset += Addend;
       Addend = 0;
     }
-    uintX_t VA = (IS->OutSec ? IS->OutSec->Addr : 0) + IS->getOffset(Offset);
+    const OutputSectionBase *OutSec = IS->getOutputSection();
+    uintX_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset);
     if (D.isTls() && !Config->Relocatable) {
       if (!Out<ELFT>::TlsPhdr)
         fatal(toString(D.File) +

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Fri Feb  3 07:06:18 2017
@@ -1152,7 +1152,7 @@ void SymbolTableSection<ELFT>::writeLoca
       ESym->st_shndx = SHN_ABS;
       ESym->st_value = Body.Value;
     } else {
-      const OutputSectionBase *OutSec = Section->OutSec;
+      const OutputSectionBase *OutSec = Section->getOutputSection();
       ESym->st_shndx = OutSec->SectionIndex;
       ESym->st_value = OutSec->Addr + Section->getOffset(Body);
     }
@@ -1218,7 +1218,7 @@ SymbolTableSection<ELFT>::getOutputSecti
   case SymbolBody::DefinedRegularKind: {
     auto &D = cast<DefinedRegular<ELFT>>(*Sym);
     if (D.Section)
-      return D.Section->OutSec;
+      return D.Section->getOutputSection();
     break;
   }
   case SymbolBody::DefinedCommonKind:
@@ -1872,6 +1872,81 @@ template <class ELFT> bool VersionNeedSe
 }
 
 template <class ELFT>
+MergeSyntheticSection<ELFT>::MergeSyntheticSection(StringRef Name,
+                                                   uint32_t Type, uintX_t Flags,
+                                                   uintX_t Alignment)
+    : SyntheticSection<ELFT>(Flags, Type, Alignment, Name),
+      Builder(StringTableBuilder::RAW, Alignment) {
+  this->Entsize = Alignment;
+}
+
+template <class ELFT>
+void MergeSyntheticSection<ELFT>::addSection(MergeInputSection<ELFT> *MS) {
+  assert(!Finalized);
+  MS->MergeSec = this;
+  Sections.push_back(MS);
+  this->Entsize = MS->Entsize;
+}
+
+template <class ELFT> void MergeSyntheticSection<ELFT>::writeTo(uint8_t *Buf) {
+  Builder.write(Buf);
+}
+
+template <class ELFT>
+bool MergeSyntheticSection<ELFT>::shouldTailMerge() const {
+  return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2;
+}
+
+template <class ELFT> void MergeSyntheticSection<ELFT>::finalizeTailMerge() {
+  // Add all string pieces to the string table builder to create section
+  // contents.
+  for (MergeInputSection<ELFT> *Sec : Sections)
+    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
+      if (Sec->Pieces[I].Live)
+        Builder.add(Sec->getData(I));
+
+  // Fix the string table content. After this, the contents will never change.
+  Builder.finalize();
+
+  // finalize() fixed tail-optimized strings, so we can now get
+  // offsets of strings. Get an offset for each string and save it
+  // to a corresponding StringPiece for easy access.
+  for (MergeInputSection<ELFT> *Sec : Sections)
+    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
+      if (Sec->Pieces[I].Live)
+        Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I));
+}
+
+template <class ELFT> void MergeSyntheticSection<ELFT>::finalizeNoTailMerge() {
+  // Add all string pieces to the string table builder to create section
+  // contents. Because we are not tail-optimizing, offsets of strings are
+  // fixed when they are added to the builder (string table builder contains
+  // a hash table from strings to offsets).
+  for (MergeInputSection<ELFT> *Sec : Sections)
+    for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)
+      if (Sec->Pieces[I].Live)
+        Sec->Pieces[I].OutputOff = Builder.add(Sec->getData(I));
+
+  Builder.finalizeInOrder();
+}
+
+template <class ELFT> void MergeSyntheticSection<ELFT>::finalize() {
+  if (Finalized)
+    return;
+  Finalized = true;
+  if (shouldTailMerge())
+    finalizeTailMerge();
+  else
+    finalizeNoTailMerge();
+}
+
+template <class ELFT> size_t MergeSyntheticSection<ELFT>::getSize() const {
+  // We should finalize string builder to know the size.
+  const_cast<MergeSyntheticSection<ELFT> *>(this)->finalize();
+  return Builder.getSize();
+}
+
+template <class ELFT>
 MipsRldMapSection<ELFT>::MipsRldMapSection()
     : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
                              sizeof(typename ELFT::uint), ".rld_map") {}
@@ -2064,6 +2139,11 @@ template class elf::VersionDefinitionSec
 template class elf::VersionDefinitionSection<ELF64LE>;
 template class elf::VersionDefinitionSection<ELF64BE>;
 
+template class elf::MergeSyntheticSection<ELF32LE>;
+template class elf::MergeSyntheticSection<ELF32BE>;
+template class elf::MergeSyntheticSection<ELF64LE>;
+template class elf::MergeSyntheticSection<ELF64BE>;
+
 template class elf::MipsRldMapSection<ELF32LE>;
 template class elf::MipsRldMapSection<ELF32BE>;
 template class elf::MipsRldMapSection<ELF64LE>;

Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Fri Feb  3 07:06:18 2017
@@ -39,7 +39,7 @@ template <class ELFT> class SyntheticSec
 public:
   SyntheticSection(uintX_t Flags, uint32_t Type, uintX_t Addralign,
                    StringRef Name)
-      : InputSection<ELFT>(Flags, Type, Addralign, ArrayRef<uint8_t>(), Name,
+      : InputSection<ELFT>(Flags, Type, Addralign, {}, Name,
                            InputSectionData::Synthetic) {
     this->Live = true;
   }
@@ -629,6 +629,32 @@ public:
   bool empty() const override;
 };
 
+// MergeSyntheticSection is a class that allows us to put mergeable sections
+// with different attributes in a single output sections. To do that
+// we put them into MergeSyntheticSection synthetic input sections which are
+// attached to regular output sections.
+template <class ELFT>
+class MergeSyntheticSection final : public SyntheticSection<ELFT> {
+  typedef typename ELFT::uint uintX_t;
+
+public:
+  MergeSyntheticSection(StringRef Name, uint32_t Type, uintX_t Flags,
+                        uintX_t Alignment);
+  void addSection(MergeInputSection<ELFT> *MS);
+  void writeTo(uint8_t *Buf) override;
+  void finalize() override;
+  bool shouldTailMerge() const;
+  size_t getSize() const override;
+
+private:
+  void finalizeTailMerge();
+  void finalizeNoTailMerge();
+
+  bool Finalized = false;
+  llvm::StringTableBuilder Builder;
+  std::vector<MergeInputSection<ELFT> *> Sections;
+};
+
 // .MIPS.abiflags section.
 template <class ELFT>
 class MipsAbiFlagsSection final : public SyntheticSection<ELFT> {

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Feb  3 07:06:18 2017
@@ -148,11 +148,60 @@ template <class ELFT> void Writer<ELFT>:
   Phdrs.erase(I, Phdrs.end());
 }
 
+template <class ELFT>
+static typename ELFT::uint getOutFlags(InputSectionBase<ELFT> *S) {
+  return S->Flags & ~(typename ELFT::uint)(SHF_GROUP | SHF_COMPRESSED);
+}
+
+// This function scans over the input sections and creates mergeable
+// synthetic sections. It removes MergeInputSections from array and
+// adds new synthetic ones. Each synthetic section is added to the
+// location of the first input section it replaces.
+template <class ELFT> static void combineMergableSections() {
+  typedef typename ELFT::uint uintX_t;
+
+  std::vector<MergeSyntheticSection<ELFT> *> MergeSections;
+  for (InputSectionBase<ELFT> *&S : Symtab<ELFT>::X->Sections) {
+    MergeInputSection<ELFT> *MS = dyn_cast<MergeInputSection<ELFT>>(S);
+    if (!MS)
+      continue;
+
+    // We do not want to handle sections that are not alive, so just remove
+    // them instead of trying to merge.
+    if (!MS->Live)
+      continue;
+
+    StringRef OutsecName = getOutputSectionName(MS->Name);
+    uintX_t Flags = getOutFlags(MS);
+    uintX_t Alignment = std::max<uintX_t>(MS->Alignment, MS->Entsize);
+
+    auto I =
+        llvm::find_if(MergeSections, [=](MergeSyntheticSection<ELFT> *Sec) {
+          return Sec->Name == OutsecName && Sec->Flags == Flags &&
+                 Sec->Alignment == Alignment;
+        });
+    if (I == MergeSections.end()) {
+      MergeSyntheticSection<ELFT> *Syn = make<MergeSyntheticSection<ELFT>>(
+          OutsecName, MS->Type, Flags, Alignment);
+      MergeSections.push_back(Syn);
+      I = std::prev(MergeSections.end());
+      S = Syn;
+    } else {
+      S = nullptr;
+    }
+    (*I)->addSection(MS);
+  }
+
+  std::vector<InputSectionBase<ELFT> *> &V = Symtab<ELFT>::X->Sections;
+  V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
+}
+
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
   // Create linker-synthesized sections such as .got or .plt.
   // Such sections are of type input section.
   createSyntheticSections();
+  combineMergableSections<ELFT>();
 
   // We need to create some reserved symbols such as _end. Create them.
   if (!Config->Relocatable)
@@ -973,8 +1022,9 @@ finalizeSynthetic(const std::vector<Synt
 // sometimes. This function filters out such unused sections from output.
 template <class ELFT>
 static void removeUnusedSyntheticSections(std::vector<OutputSectionBase *> &V) {
-  // Input synthetic sections are placed after all regular ones. We iterate over
-  // them all and exit at first non-synthetic.
+  // All input synthetic sections that can be empty are placed after
+  // all regular ones. We iterate over them all and exit at first
+  // non-synthetic.
   for (InputSectionBase<ELFT> *S : llvm::reverse(Symtab<ELFT>::X->Sections)) {
     SyntheticSection<ELFT> *SS = dyn_cast<SyntheticSection<ELFT>>(S);
     if (!SS)

Modified: lld/trunk/test/ELF/linkerscript/alternate-sections.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/alternate-sections.s?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/alternate-sections.s (original)
+++ lld/trunk/test/ELF/linkerscript/alternate-sections.s Fri Feb  3 07:06:18 2017
@@ -4,25 +4,27 @@
 # RUN: ld.lld -o %t --script %t.script %t.o -shared
 # RUN: llvm-readobj -s -section-data %t | FileCheck %s
 
-# This test shows an oddity in lld. When a linker script alternates among
-# different types of output section in the same command, the sections are
-# reordered.
-# In this test we go from regular, to merge and back to regular. The reason
-# for the reordering is that we need two create two output sections and
-# one cannot be in the middle of another.
-# If this ever becomes a problem, some options would be:
-# * Adding an extra layer in between input section and output sections (Chunk).
-#   With that this example would have 3 chunks, but only one output section.
-#   This would unfortunately complicate the non-script case too.
-# * Just create three output sections.
-# * If having three output sections causes problem, have linkerscript specific
-#   code to write the section table and section indexes. That way we could
-#   keep 3 sections internally but not expose that.
-
-# CHECK: Name: abc
-# CHECK: 0000: 01000000 00000000 02000000 00000000  |
-# CHECK: Name: abc
-# CHECK: 0000: 61626331 323300                      |abc123.|
+# CHECK:       Section {
+# CHECK:        Index:
+# CHECK:        Name: abc
+# CHECK-NEXT:   Type: SHT_PROGBIT
+# CHECK-NEXT:   Flags [
+# CHECK-NEXT:     SHF_ALLOC
+# CHECK-NEXT:     SHF_MERGE
+# CHECK-NEXT:     SHF_STRINGS
+# CHECK-NEXT:   ]
+# CHECK-NEXT:   Address:
+# CHECK-NEXT:   Offset:
+# CHECK-NEXT:   Size:
+# CHECK-NEXT:   Link:
+# CHECK-NEXT:   Info:
+# CHECK-NEXT:   AddressAlignment:
+# CHECK-NEXT:   EntrySize:
+# CHECK-NEXT:   SectionData (
+# CHECK-NEXT:     0000: 01000000 00000000 61626331 32330002  |........abc123..|
+# CHECK-NEXT:     0010: 00000000 000000                      |.......|
+# CHECK-NEXT:   )
+# CHECK-NEXT: }
 
         .section foo, "a"
         .quad 1

Added: lld/trunk/test/ELF/linkerscript/merge-sections-syms.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/merge-sections-syms.s?rev=294005&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/merge-sections-syms.s (added)
+++ lld/trunk/test/ELF/linkerscript/merge-sections-syms.s Fri Feb  3 07:06:18 2017
@@ -0,0 +1,49 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+# RUN: echo "SECTIONS { \
+# RUN:   . = SIZEOF_HEADERS; \
+# RUN:   .rodata : { *(.aaa) *(.bbb) A = .; *(.ccc) B = .; } \
+# RUN: }" > %t.script
+# RUN: ld.lld -o %t.so --script %t.script %t.o -shared
+# RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s
+
+# CHECK:      DynamicSymbols [
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name:
+# CHECK-NEXT:     Value:
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Binding:
+# CHECK-NEXT:     Type:
+# CHECK-NEXT:     Other:
+# CHECK-NEXT:     Section:
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: A
+# CHECK-NEXT:     Value: 0x195
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Binding:
+# CHECK-NEXT:     Type:
+# CHECK-NEXT:     Other:
+# CHECK-NEXT:     Section:
+# CHECK-NEXT:   }
+# CHECK-NEXT:   Symbol {
+# CHECK-NEXT:     Name: B
+# CHECK-NEXT:     Value: 0x196
+# CHECK-NEXT:     Size:
+# CHECK-NEXT:     Binding:
+# CHECK-NEXT:     Type:
+# CHECK-NEXT:     Other:
+# CHECK-NEXT:     Section:
+# CHECK-NEXT:   }
+# CHECK-NEXT: ]
+
+
+.section .aaa,"a"
+.byte 11
+
+.section .bbb,"aMS", at progbits,1
+.asciz "foo"
+
+.section .ccc,"a"
+.byte 33

Modified: lld/trunk/test/ELF/linkerscript/merge-sections.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/merge-sections.s?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/merge-sections.s (original)
+++ lld/trunk/test/ELF/linkerscript/merge-sections.s Fri Feb  3 07:06:18 2017
@@ -17,61 +17,19 @@
 # CHECK-NEXT:   ]
 # CHECK-NEXT:   Address: 0x[[ADDR1:.*]]
 # CHECK-NEXT:   Offset: 0x[[ADDR1]]
-# CHECK-NEXT:   Size: 4
-# CHECK-NEXT:   Link: 0
-# CHECK-NEXT:   Info: 0
-# CHECK-NEXT:   AddressAlignment: 1
-# CHECK-NEXT:   EntrySize: 1
-# CHECK-NEXT: }
-# CHECK-NEXT: Section {
-# CHECK-NEXT:   Index:
-# CHECK-NEXT:   Name: .foo
-# CHECK-NEXT:   Type: SHT_PROGBITS
-# CHECK-NEXT:   Flags [
-# CHECK-NEXT:     SHF_ALLOC
-# CHECK-NEXT:     SHF_MERGE
-# CHECK-NEXT:   ]
-# CHECK-NEXT:   Address: 0x
-# CHECK-NEXT:   Offset: 0x
-# CHECK-NEXT:   Size: 1
-# CHECK-NEXT:   Link: 0
-# CHECK-NEXT:   Info: 0
-# CHECK-NEXT:   AddressAlignment: 1
-# CHECK-NEXT:   EntrySize: 1
-# CHECK-NEXT: }
-# CHECK-NEXT: Section {
-# CHECK-NEXT:   Index:
-# CHECK-NEXT:   Name: .foo
-# CHECK-NEXT:   Type: SHT_PROGBITS
-# CHECK-NEXT:   Flags [
-# CHECK-NEXT:     SHF_ALLOC
-# CHECK-NEXT:     SHF_MERGE
-# CHECK-NEXT:   ]
-# CHECK-NEXT:   Address: 0x
-# CHECK-NEXT:   Offset: 0x
-# CHECK-NEXT:   Size: 2
+# CHECK-NEXT:   Size: 14
 # CHECK-NEXT:   Link: 0
 # CHECK-NEXT:   Info: 0
 # CHECK-NEXT:   AddressAlignment: 2
-# CHECK-NEXT:   EntrySize: 2
+# CHECK-NEXT:   EntrySize: 1
 # CHECK-NEXT: }
-# CHECK-NEXT: Section {
-# CHECK-NEXT:   Index:
-# CHECK-NEXT:   Name:
-# CHECK-NEXT:   Type:
-# CHECK-NEXT:   Flags [
-# CHECK-NEXT:     SHF_ALLOC
-# CHECK-NEXT:     SHF_EXECINSTR
-# CHECK-NEXT:   ]
-# CHECK-NEXT:   Address: 0x[[ADDR2:.*]]
-# CHECK-NEXT:   Offset: 0x[[ADDR2]]
-
 
 # CHECK:      Name: begin
 # CHECK-NEXT: Value: 0x[[ADDR1]]
 
 # CHECK:      Name: end
-# CHECK-NEXT: Value: 0x[[ADDR2]]
+# 0x19E = begin + sizeof(.foo) = 0x190 + 0xE
+# CHECK-NEXT: Value: 0x19E
 
 .section        .foo.1a,"aMS", at progbits,1
 .asciz "foo"

Modified: lld/trunk/test/ELF/map-file.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/map-file.s?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/test/ELF/map-file.s (original)
+++ lld/trunk/test/ELF/map-file.s Fri Feb  3 07:06:18 2017
@@ -48,6 +48,7 @@ local:
 // CHECK-NEXT: 0000000000202000 0000000000000004    16 .bss
 // CHECK-NEXT: 0000000000202000 0000000000000004    16         COMMON
 // CHECK-NEXT: 0000000000000000 0000000000000008     1 .comment
+// CHECK-NEXT: 0000000000000000 0000000000000008     1         .comment
 // CHECK-NEXT: 0000000000000000 00000000000000f0     8 .symtab
 // CHECK-NEXT: 0000000000000000 00000000000000f0     8         .symtab
 // CHECK-NEXT: 0000000000000000 0000000000000039     1 .shstrtab

Modified: lld/trunk/test/ELF/merge-string-align.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/merge-string-align.s?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/test/ELF/merge-string-align.s (original)
+++ lld/trunk/test/ELF/merge-string-align.s Fri Feb  3 07:06:18 2017
@@ -34,10 +34,10 @@
 // CHECK-NEXT:   0010:  62617200                             |bar.|
 // CHECK-NEXT: )
 
-        .section        .rodata.str1.1,"aMS", at progbits,1
+        .section        .rodata2,"aMS", at progbits,1
         .asciz "foo"
 
-// CHECK:      Name: .rodata
+// CHECK:      Name: .rodata2
 // CHECK-NEXT: Type: SHT_PROGBITS
 // CHECK-NEXT: Flags [
 // CHECK-NEXT:   SHF_ALLOC

Modified: lld/trunk/test/ELF/no-merge.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/no-merge.s?rev=294005&r1=294004&r2=294005&view=diff
==============================================================================
--- lld/trunk/test/ELF/no-merge.s (original)
+++ lld/trunk/test/ELF/no-merge.s Fri Feb  3 07:06:18 2017
@@ -2,18 +2,12 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 # RUN: echo "SECTIONS { .data : {*(.data.*)} }" > %t0.script
 # RUN: ld.lld %t.o -o %t0.out --script %t0.script
-# RUN: llvm-objdump -s %t0.out | FileCheck %s --check-prefix=OPT
-# OPT:      Contents of section .data:
-# OPT-NEXT:   0000 01
-# OPT-NEXT: Contents of section .data:
-# OPT-NEXT:   0001 6100
-# OPT-NEXT: Contents of section .data:
-# OPT-NEXT:   0003 03
+# RUN: llvm-objdump -s %t0.out | FileCheck %s
 
 # RUN: ld.lld -O0 %t.o -o %t1.out --script %t0.script
-# RUN: llvm-objdump -s %t1.out | FileCheck %s --check-prefix=NOOPT
-# NOOPT:      Contents of section .data:
-# NOOPT-NEXT:   0000 01610003
+# RUN: llvm-objdump -s %t1.out | FileCheck %s
+# CHECK:      Contents of section .data:
+# CHECK-NEXT:   0000 01610003
 
 .section .data.aw,"aw", at progbits
 .byte 1




More information about the llvm-commits mailing list