Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -28,6 +28,7 @@ struct SectionPiece; template class DefinedRegular; +template class MergeSyntheticSection; template class ObjectFile; template class OutputSection; class OutputSectionBase; @@ -40,7 +41,7 @@ // section class InputSectionData { public: - enum Kind { Regular, EHFrame, Merge, Synthetic, }; + enum Kind { Regular, EHFrame, Merge, Synthetic, MergeSynthetic }; // The garbage collector sets sections' Live bits. // If GC is disabled, all sections are considered live by default. @@ -206,6 +207,11 @@ 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 *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 @@ -80,7 +80,9 @@ // 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)) + bool IsMergeSec = isa>(this) || + isa>(this); + if (!Config->Relocatable && !IsMergeSec) this->Flags &= ~(SHF_MERGE | SHF_STRINGS); } @@ -122,7 +124,8 @@ // identify the start of the output .eh_frame. return Offset; case Merge: - return cast>(this)->getOffset(Offset); + const MergeInputSection *MS = cast>(this); + return (MS->MergeSec ? MS->MergeSec->OutSecOff : 0) + MS->getOffset(Offset); } llvm_unreachable("invalid section kind"); } @@ -204,7 +207,8 @@ template bool InputSection::classof(const InputSectionData *S) { - return S->kind() == Base::Regular || S->kind() == Base::Synthetic; + return S->kind() == Base::Regular || S->kind() == Base::Synthetic || + S->kind() == Base::MergeSynthetic; } template Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -129,30 +129,6 @@ 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; -}; - struct CieRecord { EhSectionPiece *Piece = nullptr; std::vector FdePieces; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -133,9 +133,11 @@ Sections.push_back(S); S->OutSec = this; this->updateAlignment(S->Alignment); - // Keep sh_entsize value of the input section to be able to perform merging - // later during a final linking using the generated relocatable object. - if (Config->Relocatable && (S->Flags & SHF_MERGE)) + // Keep sh_entsize value of the input section during relocatable output to be + // able to perform merging later during a final linking using the generated + // relocatable object. Also keep value for mergeable sections. + if (isa>(C) || + (Config->Relocatable && (S->Flags & SHF_MERGE))) this->Entsize = S->Entsize; } @@ -479,71 +481,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; } @@ -602,24 +539,15 @@ // // 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>(C) || - (Config->Relocatable && (C->Flags & SHF_MERGE))) + uintX_t Flags = 0; + if (Config->Relocatable && (C->Flags & SHF_MERGE)) { Alignment = std::max(C->Alignment, C->Entsize); + Flags = C->Flags & (SHF_MERGE | SHF_STRINGS); + } return SectionKey{OutsecName, Flags, Alignment}; } @@ -664,17 +592,9 @@ } 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; - } + Sec = make>(Key.Name, Type, Flags); return {Sec, true}; } @@ -714,11 +634,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/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -63,7 +63,10 @@ Offset += Addend; Addend = 0; } - uintX_t VA = (IS->OutSec ? IS->OutSec->Addr : 0) + IS->getOffset(Offset); + + const OutputSectionBase *OutSec = + SymbolTableSection::getOutputSection(&Body); + uintX_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset(Offset); if (D.isTls() && !Config->Relocatable) { if (!Out::TlsPhdr) fatal(toString(D.File) + Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -35,12 +35,12 @@ template class SyntheticSection : public InputSection { typedef typename ELFT::uint uintX_t; + typedef InputSectionData::Kind Kind; public: SyntheticSection(uintX_t Flags, uint32_t Type, uintX_t Addralign, - StringRef Name) - : InputSection(Flags, Type, Addralign, ArrayRef(), Name, - InputSectionData::Synthetic) { + StringRef Name, Kind Kind = InputSectionData::Synthetic) + : InputSection(Flags, Type, Addralign, {}, Name, Kind) { this->Live = true; } @@ -55,7 +55,8 @@ } static bool classof(const InputSectionData *D) { - return D->kind() == InputSectionData::Synthetic; + return D->kind() == InputSectionData::Synthetic || + D->kind() == InputSectionData::MergeSynthetic; } }; @@ -389,7 +390,7 @@ ArrayRef getSymbols() const { return Symbols; } - static const OutputSectionBase *getOutputSection(SymbolBody *Sym); + static const OutputSectionBase *getOutputSection(const SymbolBody *Sym); private: void writeLocalSymbols(uint8_t *&Buf); @@ -629,6 +630,36 @@ 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 MergeSyntheticSection final : public SyntheticSection { + typedef typename ELFT::uint uintX_t; + +public: + MergeSyntheticSection(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; + + static bool classof(const InputSectionData *D) { + return D->kind() == InputSectionData::MergeSynthetic; + } + +private: + void finalizeTailMerge(); + void finalizeNoTailMerge(); + + bool Finalized = false; + llvm::StringTableBuilder Builder; + std::vector *> Sections; +}; + // .MIPS.abiflags section. template class MipsAbiFlagsSection final : public SyntheticSection { @@ -701,7 +732,7 @@ template InputSection *createCommonSection(); template InputSection *createInterpSection(); -template MergeInputSection *createCommentSection(); +template MergeSyntheticSection *createCommentSection(); template SymbolBody * addSyntheticLocal(StringRef Name, uint8_t Type, typename ELFT::uint Value, Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -102,16 +102,20 @@ // With this feature, you can identify LLD-generated binaries easily // by "objdump -s -j .comment ". // The returned object is a mergeable string section. -template MergeInputSection *elf::createCommentSection() { +template MergeSyntheticSection *elf::createCommentSection() { typename ELFT::Shdr Hdr = {}; Hdr.sh_flags = SHF_MERGE | SHF_STRINGS; Hdr.sh_type = SHT_PROGBITS; Hdr.sh_entsize = 1; Hdr.sh_addralign = 1; - auto *Ret = make>(/*file=*/nullptr, &Hdr, ".comment"); - Ret->Data = getVersion(); - Ret->splitIntoPieces(); + auto *MS = make>(/*file=*/nullptr, &Hdr, ".comment"); + MS->Data = getVersion(); + MS->splitIntoPieces(); + + auto *Ret = make>(".comment", Hdr.sh_type, + Hdr.sh_flags, Hdr.sh_addralign); + Ret->addSection(MS); return Ret; } @@ -1152,7 +1156,8 @@ ESym->st_shndx = SHN_ABS; ESym->st_value = Body.Value; } else { - const OutputSectionBase *OutSec = Section->OutSec; + const OutputSectionBase *OutSec = + SymbolTableSection::getOutputSection(I->Symbol); ESym->st_shndx = OutSec->SectionIndex; ESym->st_value = OutSec->Addr + Section->getOffset(Body); } @@ -1211,14 +1216,19 @@ template const OutputSectionBase * -SymbolTableSection::getOutputSection(SymbolBody *Sym) { +SymbolTableSection::getOutputSection(const SymbolBody *Sym) { switch (Sym->kind()) { case SymbolBody::DefinedSyntheticKind: return cast(Sym)->Section; case SymbolBody::DefinedRegularKind: { auto &D = cast>(*Sym); - if (D.Section) - return D.Section->OutSec; + if (D.Section) { + // MergeInputSections were merged into synthetic merge sections. + OutputSectionBase *OutSec = D.Section->OutSec; + if (auto *MS = dyn_cast>(D.Section)) + OutSec = MS->MergeSec ? MS->MergeSec->OutSec : nullptr; + return OutSec; + } break; } case SymbolBody::DefinedCommonKind: @@ -1872,6 +1882,80 @@ } template +MergeSyntheticSection::MergeSyntheticSection(StringRef Name, + uint32_t Type, uintX_t Flags, + uintX_t Alignment) + : SyntheticSection(Flags, Type, Alignment, Name, + InputSectionData::MergeSynthetic), + Builder(StringTableBuilder::RAW, Alignment) {} + +template +void MergeSyntheticSection::addSection(MergeInputSection *MS) { + assert(!Finalized); + MS->MergeSec = this; + Sections.push_back(MS); + this->Entsize = MS->Entsize; +} + +template void MergeSyntheticSection::writeTo(uint8_t *Buf) { + Builder.write(Buf); +} + +template +bool MergeSyntheticSection::shouldTailMerge() const { + return (this->Flags & SHF_STRINGS) && Config->Optimize >= 2; +} + +template void MergeSyntheticSection::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 MergeSyntheticSection::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 void MergeSyntheticSection::finalize() { + if (Finalized) + return; + Finalized = true; + if (shouldTailMerge()) + finalizeTailMerge(); + else + finalizeNoTailMerge(); +} + +template size_t MergeSyntheticSection::getSize() const { + // We should finalize string builder to know the size. + const_cast *>(this)->finalize(); + return Builder.getSize(); +} + +template MipsRldMapSection::MipsRldMapSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, sizeof(typename ELFT::uint), ".rld_map") {} @@ -1914,10 +1998,10 @@ template InputSection *elf::createInterpSection(); template InputSection *elf::createInterpSection(); -template MergeInputSection *elf::createCommentSection(); -template MergeInputSection *elf::createCommentSection(); -template MergeInputSection *elf::createCommentSection(); -template MergeInputSection *elf::createCommentSection(); +template MergeSyntheticSection *elf::createCommentSection(); +template MergeSyntheticSection *elf::createCommentSection(); +template MergeSyntheticSection *elf::createCommentSection(); +template MergeSyntheticSection *elf::createCommentSection(); template SymbolBody * elf::addSyntheticLocal(StringRef, uint8_t, ELF32LE::uint, @@ -2037,6 +2121,11 @@ template class elf::VersionDefinitionSection; template class elf::VersionDefinitionSection; +template class elf::MergeSyntheticSection; +template class elf::MergeSyntheticSection; +template class elf::MergeSyntheticSection; +template class elf::MergeSyntheticSection; + template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; template class elf::MipsRldMapSection; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -148,11 +148,58 @@ 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 static void combineMergableSections() { + typedef typename ELFT::uint uintX_t; + + std::vector *> MergeSections; + auto DoMerge = [&](InputSectionBase *S) { + MergeInputSection *MS = dyn_cast>(S); + if (!MS) + return false; + + // We do not want to handle sections that are not alive, so just remove + // them instead of trying to merge. + if (!MS->Live) + return true; + + 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, [=](MergeSyntheticSection *Sec) { + return Sec->Name == OutsecName && Sec->Flags == Flags && + Sec->Alignment == Alignment; + }); + if (I == MergeSections.end()) { + MergeSyntheticSection *Syn = make>( + OutsecName, MS->Type, Flags, Alignment); + MergeSections.push_back(Syn); + I = std::prev(MergeSections.end()); + } + (*I)->addSection(MS); + + return true; + }; + + std::vector *> &V = Symtab::X->Sections; + 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. // Such sections are of type input section. createSyntheticSections(); + combineMergableSections(); // We need to create some reserved symbols such as _end. Create them. if (!Config->Relocatable) Index: test/ELF/comment-gc.s =================================================================== --- test/ELF/comment-gc.s +++ test/ELF/comment-gc.s @@ -5,7 +5,7 @@ # RUN: llvm-objdump -s %t1 | FileCheck %s # CHECK: Contents of section .comment: -# CHECK-NEXT: 0000 00666f6f 00626172 004c4c44 20312e30 .foo.bar.LLD 1.0 +# CHECK-NEXT: 0000 4c4c4420 312e3000 00666f6f 00626172 LLD 1.0..foo.bar # CHECK-NEXT: 0010 00 . .ident "foo" 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,7 +9,7 @@ // 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 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 61626331 32330002 |........abc123..| +# CHECK-NEXT: 0010: 00000000 000000 |.......| +# 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: } -# 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/map-file.s =================================================================== --- test/ELF/map-file.s +++ test/ELF/map-file.s @@ -48,6 +48,7 @@ // CHECK-NEXT: 0000000000202000 0000000000000004 4 .bss // CHECK-NEXT: 0000000000202000 0000000000000004 4 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 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,16 @@ // 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: ) 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: 2 // 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: 2 // 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/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"