[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