Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -27,6 +27,7 @@ struct SectionPiece; template class DefinedRegular; +template class MergeSection; template class ObjectFile; template class OutputSection; class OutputSectionBase; @@ -214,6 +215,11 @@ SectionPiece *getSectionPiece(uintX_t Offset); const SectionPiece *getSectionPiece(uintX_t Offset) const; + // Mergeable input sections with different attributes are placed to + // synthetic sections which are parts of regular output section. + // That way we can emit a single output section at the end. + MergeSection *MergeSec = nullptr; + private: void splitStrings(ArrayRef A, size_t Size); void splitNonStrings(ArrayRef A, size_t Size); Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -84,7 +84,8 @@ // 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>(this)) + if (!Config->Relocatable && !isa>(this) && + !isa>(this)) this->Flags &= ~(SHF_MERGE | SHF_STRINGS); } @@ -130,8 +131,10 @@ // .eh_frame that is known to be the first in the link. It does that to // identify the start of the output .eh_frame. return Offset; - case Merge: - return cast>(this)->getOffset(Offset); + case Merge: { + const MergeInputSection *MS = cast>(this); + return MS->MergeSec ? MS->MergeSec->OutSecOff + MS->getOffset(Offset) : 0; + } } llvm_unreachable("invalid section kind"); } Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -267,30 +267,9 @@ template static SectionKey createKey(InputSectionBase *C, StringRef OutsecName) { - // When using linker script the merge rules are different. - // Unfortunately, linker scripts are name based. This means that expressions - // like *(.foo*) can refer to multiple input sections that would normally be - // placed in different output sections. We cannot put them in different - // output sections or we would produce wrong results for - // start = .; *(.foo.*) end = .; *(.bar) - // and a mapping of .foo1 and .bar1 to one section and .foo2 and .bar2 to - // another. The problem is that there is no way to layout those output - // sections such that the .foo sections are the only thing between the - // start and end symbols. - - // An extra annoyance is that we cannot simply disable merging of the contents - // of SHF_MERGE sections, but our implementation requires one output section - // per "kind" (string or not, which size/aligment). - // Fortunately, creating symbols in the middle of a merge section is not - // supported by bfd or gold, so we can just create multiple section in that - // case. typedef typename ELFT::uint uintX_t; - uintX_t Flags = C->Flags & (SHF_MERGE | SHF_STRINGS); - + uintX_t Flags = 0; uintX_t Alignment = 0; - if (isa>(C)) - Alignment = std::max(C->Alignment, C->Entsize); - return SectionKey{OutsecName, /*Type*/ 0, Flags, Alignment}; } @@ -369,6 +348,8 @@ S->Alignment = Subalign; } + combineMergableSections(V); + // Add input sections to an output section. for (InputSectionBase *S : V) addSection(Factory, S, Cmd->Name); @@ -379,9 +360,13 @@ // Add sections that didn't match any sections command. template void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { - for (InputSectionBase *S : Symtab::X->Sections) - if (S->Live && !S->OutSec) - addSection(Factory, S, getOutputSectionName(S->Name)); + for (InputSectionBase *S : Symtab::X->Sections) { + if (S->Live && !S->OutSec) { + std::vector *> V = { S }; + combineMergableSections(V); + addSection(Factory, V[0], getOutputSectionName(S->Name)); + } + } } // Sets value of a section-defined symbol. Two kinds of Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -26,6 +26,7 @@ template class InputSection; template class InputSectionBase; template class MergeInputSection; +template class MergeSection; template class OutputSection; template class ObjectFile; template class SharedFile; @@ -124,30 +125,9 @@ // Location in the output buffer. uint8_t *Loc = nullptr; -}; - -template -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 *> Sections; + std::vector *> MergeSections; }; struct CieRecord { Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -129,6 +129,11 @@ template void OutputSection::addSection(InputSectionData *C) { assert(C->Live); + + auto *SS = dyn_cast>(C); + if (SS && SS->Mergeable) + static_cast *>(SS)->setOutputSection(this); + auto *S = cast>(C); Sections.push_back(S); S->OutSec = this; @@ -465,71 +470,6 @@ } template -MergeOutputSection::MergeOutputSection(StringRef Name, uint32_t Type, - uintX_t Flags, uintX_t Alignment) - : OutputSectionBase(Name, Type, Flags), - Builder(StringTableBuilder::RAW, Alignment) {} - -template void MergeOutputSection::writeTo(uint8_t *Buf) { - Builder.write(Buf); -} - -template -void MergeOutputSection::addSection(InputSectionData *C) { - auto *Sec = cast>(C); - Sec->OutSec = this; - this->updateAlignment(Sec->Alignment); - this->Entsize = Sec->Entsize; - Sections.push_back(Sec); -} - -template bool MergeOutputSection::shouldTailMerge() const { - return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2; -} - -template void MergeOutputSection::finalizeTailMerge() { - // Add all string pieces to the string table builder to create section - // contents. - for (MergeInputSection *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 *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 void MergeOutputSection::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 *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 void MergeOutputSection::finalize() { - if (shouldTailMerge()) - finalizeTailMerge(); - else - finalizeNoTailMerge(); -} - -template static typename ELFT::uint getOutFlags(InputSectionBase *S) { return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; } @@ -540,16 +480,14 @@ typedef typename ELFT::uint uintX_t; uintX_t Flags = getOutFlags(C); - // For SHF_MERGE we create different output sections for each alignment. - // This makes each output section simple and keeps a single level mapping from - // input to output. // 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. uintX_t Alignment = 0; - if (isa>(C) || - (Config->Relocatable && (C->Flags & SHF_MERGE))) + if (Config->Relocatable && (C->Flags & SHF_MERGE)) Alignment = std::max(C->Alignment, C->Entsize); + else + Flags &= ~(SHF_MERGE | SHF_STRINGS); return SectionKey{OutsecName, C->Type, Flags, Alignment}; } @@ -573,18 +511,11 @@ return {Sec, false}; } - uint32_t Type = C->Type; - switch (C->kind()) { - case InputSectionBase::Regular: - case InputSectionBase::Synthetic: - Sec = make>(Key.Name, Type, Flags); - break; - case InputSectionBase::EHFrame: + if (C->kind() == InputSectionBase::EHFrame) return {Out::EhFrame, false}; - case InputSectionBase::Merge: - Sec = make>(Key.Name, Type, Flags, Key.Alignment); - break; - } + + uint32_t Type = C->Type; + Sec = make>(Key.Name, Type, Flags); return {Sec, true}; } @@ -638,11 +569,6 @@ template class EhOutputSection; template class EhOutputSection; -template class MergeOutputSection; -template class MergeOutputSection; -template class MergeOutputSection; -template class MergeOutputSection; - template class OutputSectionFactory; template class OutputSectionFactory; template class OutputSectionFactory; Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -13,6 +13,7 @@ #include "GdbIndex.h" #include "InputSection.h" #include "llvm/ADT/MapVector.h" +#include "llvm/MC/StringTableBuilder.h" namespace lld { namespace elf { @@ -26,6 +27,7 @@ : InputSection(Flags, Type, Addralign, ArrayRef(), Name, InputSectionData::Synthetic) { this->Live = true; + this->Mergeable = false; } virtual ~SyntheticSection() = default; @@ -41,6 +43,8 @@ static bool classof(const InputSectionData *D) { return D->kind() == InputSectionData::Synthetic; } + + unsigned Mergeable : 1; }; template class GotSection final : public SyntheticSection { @@ -557,6 +561,31 @@ bool empty() const override; }; +// MergeSection 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 MergeSection synthetic input sections which are +// attached to regular output sections. +template class MergeSection final : public SyntheticSection { + typedef typename ELFT::uint uintX_t; + +public: + MergeSection(StringRef Name, uint32_t Type, uintX_t Flags, uintX_t Alignment); + void addSection(MergeInputSection *MS); + void writeTo(uint8_t *Buf) override; + void finalize() override; + bool shouldTailMerge() const; + size_t getSize() const override; + void setOutputSection(OutputSection* S); + +private: + void finalizeTailMerge(); + void finalizeNoTailMerge(); + + bool Finalized = false; + llvm::StringTableBuilder Builder; + std::vector *> Sections; +}; + // .MIPS.abiflags section. template class MipsAbiFlagsSection final : public SyntheticSection { Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -1669,6 +1669,85 @@ } template +MergeSection::MergeSection(StringRef Name, uint32_t Type, uintX_t Flags, + uintX_t Alignment) + : SyntheticSection(Flags, Type, Alignment, Name), + Builder(StringTableBuilder::RAW, Alignment) { + this->Mergeable = true; +} + +template +void MergeSection::addSection(MergeInputSection *MS) { + assert(!Finalized); + MS->MergeSec = this; + Sections.push_back(MS); +} + +template void MergeSection::writeTo(uint8_t *Buf) { + Builder.write(Buf); +} + +template void MergeSection::finalize() { + if (Finalized) + return; + Finalized = true; + + if (shouldTailMerge()) + finalizeTailMerge(); + else + finalizeNoTailMerge(); +} + +template bool MergeSection::shouldTailMerge() const { + return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2; +} + +template void MergeSection::finalizeTailMerge() { + // Add all string pieces to the string table builder to create section + // contents. + for (MergeInputSection *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 *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 void MergeSection::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 *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 size_t MergeSection::getSize() const { + // We should finalize string builder to know the size. + const_cast *>(this)->finalize(); + return Builder.getSize(); +} + +template +void MergeSection::setOutputSection(OutputSection *S) { + for (MergeInputSection *MS : Sections) + MS->OutSec = S; +} + +template MipsRldMapSection::MipsRldMapSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, sizeof(typename ELFT::uint), ".rld_map") {} @@ -1810,6 +1889,11 @@ template class elf::VersionDefinitionSection; template class elf::VersionDefinitionSection; +template class elf::MergeSection; +template class elf::MergeSection; +template class elf::MergeSection; +template class elf::MergeSection; + template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; Index: ELF/Writer.h =================================================================== --- ELF/Writer.h +++ ELF/Writer.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include #include +#include namespace lld { namespace elf { @@ -42,6 +43,9 @@ template void reportDiscarded(InputSectionBase *IS); +template +void combineMergableSections(std::vector *> &V); + template uint32_t getMipsEFlags(); uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag, Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -147,6 +147,45 @@ Phdrs.erase(I, Phdrs.end()); } +template +static typename ELFT::uint getOutFlags(InputSectionBase *S) { + return S->Flags & ~SHF_GROUP & ~SHF_COMPRESSED; +} + +// This function scans over V and creates mergeable synthetic sections. It +// removes MergeInputSections from array and adds new synthetic ones to the end. +template +void elf::combineMergableSections(std::vector *> &V) { + typedef typename ELFT::uint uintX_t; + + std::vector *> MergeSections; + auto DoMerge = [&](InputSectionBase *S) { + MergeInputSection *MS = dyn_cast>(S); + if (!MS) + return false; + StringRef OutsecName = getOutputSectionName(MS->Name); + uintX_t Flags = getOutFlags(MS); + uintX_t Alignment = std::max(MS->Alignment, MS->Entsize); + + auto I = llvm::find_if(MergeSections, [=](MergeSection *Sec) { + return Sec->Name == OutsecName && Sec->Flags == Flags && + Sec->Alignment == Alignment; + }); + if (I == MergeSections.end()) { + MergeSection *Syn = + make>(OutsecName, MS->Type, Flags, Alignment); + MergeSections.push_back(Syn); + I = std::prev(MergeSections.end()); + } + (*I)->addSection(MS); + + return true; + }; + + V.erase(llvm::remove_if(V, DoMerge), V.end()); + V.insert(V.end(), MergeSections.begin(), MergeSections.end()); +} + // The main function of the writer. template void Writer::run() { // Create linker-synthesized sections such as .got or .plt. @@ -173,6 +212,7 @@ // Assign such sections using the default rule. Script::X->addOrphanSections(Factory); } else { + combineMergableSections(Symtab::X->Sections); // If linker script does not contain SECTIONS commands, create // output sections by default rules. We still need to give the // linker script a chance to run, because it might contain @@ -1666,3 +1706,8 @@ template void elf::reportDiscarded(InputSectionBase *); template void elf::reportDiscarded(InputSectionBase *); template void elf::reportDiscarded(InputSectionBase *); + +template void elf::combineMergableSections(std::vector *> &V); +template void elf::combineMergableSections(std::vector *> &V); +template void elf::combineMergableSections(std::vector *> &V); +template void elf::combineMergableSections(std::vector *> &V); Index: test/ELF/basic-aarch64.s =================================================================== --- test/ELF/basic-aarch64.s +++ test/ELF/basic-aarch64.s @@ -81,7 +81,7 @@ # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 -# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: EntrySize: # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 3 Index: test/ELF/basic-mips.s =================================================================== --- test/ELF/basic-mips.s +++ test/ELF/basic-mips.s @@ -164,7 +164,7 @@ # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 -# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 8 Index: test/ELF/basic-ppc.s =================================================================== --- test/ELF/basic-ppc.s +++ test/ELF/basic-ppc.s @@ -163,7 +163,7 @@ // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| // CHECK-NEXT: ) Index: test/ELF/basic.s =================================================================== --- test/ELF/basic.s +++ test/ELF/basic.s @@ -82,7 +82,7 @@ # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 -# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 3 Index: test/ELF/basic32.s =================================================================== --- test/ELF/basic32.s +++ test/ELF/basic32.s @@ -80,7 +80,7 @@ # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 -# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: } # CHECK-NEXT: Section { # CHECK-NEXT: Index: 3 Index: test/ELF/basic64be.s =================================================================== --- test/ELF/basic64be.s +++ test/ELF/basic64be.s @@ -175,7 +175,7 @@ # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 # CHECK-NEXT: AddressAlignment: 1 -# CHECK-NEXT: EntrySize: 1 +# CHECK-NEXT: EntrySize: 0 # CHECK-NEXT: SectionData ( # CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.| # CHECK-NEXT: ) Index: test/ELF/build-id.s =================================================================== --- test/ELF/build-id.s +++ test/ELF/build-id.s @@ -44,15 +44,15 @@ # DEFAULT: Contents of section .note.test: # DEFAULT: Contents of section .note.gnu.build-id: # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. -# DEFAULT-NEXT: d08dafb4 e6294b62 +# DEFAULT-NEXT: fd36edb1 f6ff02af # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. -# MD5-NEXT: 37 +# MD5-NEXT: fc # SHA1: Contents of section .note.gnu.build-id: # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. -# SHA1-NEXT: 7a4f4eaf 69ceb948 4a7d6e51 2225e87c +# SHA1-NEXT: 55b1eedb 03b588e1 09987d1d e9a79be7 # UUID: Contents of section .note.gnu.build-id: # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. Index: test/ELF/debug-gc.s =================================================================== --- test/ELF/debug-gc.s +++ test/ELF/debug-gc.s @@ -3,12 +3,12 @@ # RUN: ld.lld %t.o -o %t1 --gc-sections # RUN: llvm-objdump -s %t1 | FileCheck %s +# CHECK: Contents of section .debug_info: +# CHECK-NEXT: 0000 00000000 04000000 # CHECK: Contents of section .debug_str: # CHECK-NEXT: 0000 41414100 42424200 43434300 AAA.BBB.CCC. # CHECK: Contents of section .foo: # CHECK-NEXT: 0000 2a000000 -# CHECK: Contents of section .debug_info: -# CHECK-NEXT: 0000 00000000 04000000 .globl _start _start: Index: test/ELF/gc-merge-local-sym.s =================================================================== --- test/ELF/gc-merge-local-sym.s +++ test/ELF/gc-merge-local-sym.s @@ -9,13 +9,13 @@ // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: SHF_STRINGS // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1C8 +// CHECK-NEXT: Address: 0x215 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 4 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 61626300 |abc.| // CHECK-NEXT: ) Index: test/ELF/gc-sections-merge-addend.s =================================================================== --- test/ELF/gc-sections-merge-addend.s +++ test/ELF/gc-sections-merge-addend.s @@ -16,7 +16,7 @@ // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 62617200 |bar.| // CHECK-NEXT: ) Index: test/ELF/gc-sections-merge-implicit-addend.s =================================================================== --- test/ELF/gc-sections-merge-implicit-addend.s +++ test/ELF/gc-sections-merge-implicit-addend.s @@ -16,7 +16,7 @@ // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 62617200 |bar.| // CHECK-NEXT: ) Index: test/ELF/gc-sections-merge.s =================================================================== --- test/ELF/gc-sections-merge.s +++ test/ELF/gc-sections-merge.s @@ -18,7 +18,7 @@ // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 666F6F00 62617200 |foo.bar.| // CHECK-NEXT: ) @@ -36,7 +36,7 @@ // GC-NEXT: Link: 0 // GC-NEXT: Info: 0 // GC-NEXT: AddressAlignment: 1 -// GC-NEXT: EntrySize: 1 +// GC-NEXT: EntrySize: 0 // GC-NEXT: SectionData ( // GC-NEXT: 0000: 666F6F00 |foo.| // GC-NEXT: ) Index: test/ELF/i386-merge.s =================================================================== --- test/ELF/i386-merge.s +++ test/ELF/i386-merge.s @@ -9,7 +9,7 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x114 +// CHECK-NEXT: Address: 0x140 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: // CHECK-NEXT: Link: @@ -35,10 +35,10 @@ // CHECK-NEXT: AddressAlignment: 1 // CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( -// CHECK-NEXT: 0000: 14010000 | +// CHECK-NEXT: 0000: 40010000 | // CHECK-NEXT: ) -// The content of .data should be the address of .mysec. 14010000 is 0x114 in +// The content of .data should be the address of .mysec. 40010000 is 0x140 in // little endian. .data Index: test/ELF/linkerscript/alternate-sections.s =================================================================== --- test/ELF/linkerscript/alternate-sections.s +++ test/ELF/linkerscript/alternate-sections.s @@ -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 02000000 00000000 |................| +# CHECK-NEXT: 0010: 61626331 323300 |abc123.| +# CHECK-NEXT: ) +# CHECK-NEXT: } .section foo, "a" .quad 1 Index: test/ELF/linkerscript/merge-sections.s =================================================================== --- test/ELF/linkerscript/merge-sections.s +++ test/ELF/linkerscript/merge-sections.s @@ -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: 0 # 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",@progbits,1 .asciz "foo" Index: test/ELF/merge-shared-str.s =================================================================== --- test/ELF/merge-shared-str.s +++ test/ELF/merge-shared-str.s @@ -19,10 +19,10 @@ // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: SHF_STRINGS // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1C8 +// CHECK-NEXT: Address: 0x210 // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x1C9 +// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x211 // CHECK-NEXT: } // CHECK-NEXT: ] Index: test/ELF/merge-shared.s =================================================================== --- test/ELF/merge-shared.s +++ test/ELF/merge-shared.s @@ -17,10 +17,10 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1C8 +// CHECK-NEXT: Address: 0x210 // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.dyn { -// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x1CA +// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x212 // CHECK-NEXT: } // CHECK-NEXT: ] Index: test/ELF/merge-string-align.s =================================================================== --- test/ELF/merge-string-align.s +++ test/ELF/merge-string-align.s @@ -24,33 +24,18 @@ // CHECK-NEXT: ] // CHECK-NEXT: Address: // CHECK-NEXT: Offset: -// CHECK-NEXT: Size: 20 +// CHECK-NEXT: Size: 24 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 16 // CHECK-NEXT: EntrySize: // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 666F6F00 00000000 00000000 00000000 |foo.............| -// CHECK-NEXT: 0010: 62617200 |bar.| +// CHECK-NEXT: 0010: 62617200 666F6F00 |bar.foo.| // CHECK-NEXT: ) .section .rodata.str1.1,"aMS",@progbits,1 .asciz "foo" -// CHECK: Name: .rodata -// CHECK-NEXT: Type: SHT_PROGBITS -// 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: 4 -// CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: -// CHECK-NEXT: SectionData ( -// CHECK-NEXT: 0000: 666F6F00 |foo.| -// CHECK-NEXT: ) +// CHECK-NOT: Name: .rodata + Index: test/ELF/merge-string.s =================================================================== --- test/ELF/merge-string.s +++ test/ELF/merge-string.s @@ -28,15 +28,15 @@ // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: SHF_STRINGS // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1C8 -// CHECK-NEXT: Offset: 0x1C8 -// CHECK-NEXT: Size: 4 +// CHECK-NEXT: Address: 0x1F2 +// CHECK-NEXT: Offset: 0x1F2 +// CHECK-NEXT: Size: 8 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 1 +// CHECK-NEXT: AddressAlignment: 2 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( -// CHECK-NEXT: 0000: 61626300 |abc.| +// CHECK-NEXT: 0000: 61626300 14000000 |abc.....| // CHECK-NEXT: ) // NOTAIL: Name: .rodata @@ -46,15 +46,15 @@ // NOTAIL-NEXT: SHF_MERGE // NOTAIL-NEXT: SHF_STRINGS // NOTAIL-NEXT: ] -// NOTAIL-NEXT: Address: 0x1C8 -// NOTAIL-NEXT: Offset: 0x1C8 -// NOTAIL-NEXT: Size: 7 +// NOTAIL-NEXT: Address: 0x1F2 +// NOTAIL-NEXT: Offset: 0x1F2 +// NOTAIL-NEXT: Size: 12 // NOTAIL-NEXT: Link: 0 // NOTAIL-NEXT: Info: 0 -// NOTAIL-NEXT: AddressAlignment: 1 -// NOTAIL-NEXT: EntrySize: 1 +// NOTAIL-NEXT: AddressAlignment: 2 +// NOTAIL-NEXT: EntrySize: 0 // NOTAIL-NEXT: SectionData ( -// NOTAIL-NEXT: 0000: 61626300 626300 |abc.bc.| +// NOTAIL-NEXT: 0000: 61626300 62630000 14000000 |abc.bc......| // NOTAIL-NEXT: ) // NOMERGE: Name: .rodata @@ -73,31 +73,12 @@ // NOMERGE-NEXT: 0000: 61626300 61626300 62630000 14000000 |abc.abc.bc......| // NOMERGE-NEXT: ) -// CHECK: Name: .rodata -// CHECK-NEXT: Type: SHT_PROGBITS -// CHECK-NEXT: Flags [ -// CHECK-NEXT: SHF_ALLOC -// CHECK-NEXT: SHF_MERGE -// CHECK-NEXT: SHF_STRINGS -// CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1CC -// CHECK-NEXT: Offset: 0x1CC -// CHECK-NEXT: Size: 4 -// CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 2 -// CHECK-NEXT: EntrySize: 2 -// CHECK-NEXT: SectionData ( -// CHECK-NEXT: 0000: 14000000 |....| -// CHECK-NEXT: ) - - // CHECK: Name: bar -// CHECK-NEXT: Value: 0x1C9 +// CHECK-NEXT: Value: 0x1F3 // CHECK: Name: foo -// CHECK-NEXT: Value: 0x1C8 +// CHECK-NEXT: Value: 0x1F2 // CHECK: Name: zed -// CHECK-NEXT: Value: 0x1CC +// CHECK-NEXT: Value: 0x1F6 // CHECK-NEXT: Size: 0 Index: test/ELF/merge-sym.s =================================================================== --- test/ELF/merge-sym.s +++ test/ELF/merge-sym.s @@ -15,7 +15,7 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_MERGE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1C8 +// CHECK-NEXT: Address: 0x1F4 // CHECK: Name: foo -// CHECK-NEXT: Value: 0x1CA +// CHECK-NEXT: Value: 0x1F6 Index: test/ELF/merge.s =================================================================== --- test/ELF/merge.s +++ test/ELF/merge.s @@ -29,7 +29,7 @@ // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 // CHECK-NEXT: AddressAlignment: 4 -// CHECK-NEXT: EntrySize: 4 +// CHECK-NEXT: EntrySize: 0 // CHECK-NEXT: SectionData ( // CHECK-NEXT: 0000: 10000000 42000000 // CHECK-NEXT: ) Index: test/ELF/no-merge.s =================================================================== --- test/ELF/no-merge.s +++ test/ELF/no-merge.s @@ -4,22 +4,18 @@ # 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 +# OPT-NEXT: 0000 61626300 abc. # 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 +# NOOPT-NEXT: 0000 61626300 61626300 61626300 abc.abc.abc. -.section .data.aw,"aw",@progbits -.byte 1 +.section .data.ams1,"aMS",@progbits,1 +.asciz "abc" -.section .data.ams,"aMS",@progbits,1 -.asciz "a" +.section .data.ams2,"aMS",@progbits,1 +.asciz "abc" -.section .data.am,"aM",@progbits,1 -.byte 3 +.section .data.ams3,"aMS",@progbits,1 +.asciz "abc"