Index: ELF/InputSection.h =================================================================== --- ELF/InputSection.h +++ ELF/InputSection.h @@ -318,13 +318,15 @@ OutputSection *getParent() const; - // The offset from beginning of the output sections this section was assigned - // to. The writer sets a value. - uint64_t OutSecOff = 0; - - static bool classof(const SectionBase *S); - - InputSectionBase *getRelocatedSection(); + // This variable has two usages. Initially, it represents an index in the + // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER + // sections. After assignAddresses is called, it represents the offset from + // the beginning of the output section this section was assigned to. + uint64_t OutSecOff = 0; + + static bool classof(const SectionBase *S); + + InputSectionBase *getRelocatedSection(); template void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef Rels); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -674,6 +674,11 @@ if (Ctx->OutSec->Flags & SHF_COMPRESSED) return; + // The Size previously denoted how many InputSections had been added to this + // section, and was used for sorting SHF_LINK_ORDER sections. Reset it to + // compute the actual size value. + Sec->Size = 0; + // We visited SectionsCommands from processSectionCommands to // layout sections. Now, we visit SectionsCommands again to fix // section offsets. Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -71,8 +71,12 @@ // it may have a non-null value. OutputSection *RelocationSection = nullptr; - // The following fields correspond to Elf_Shdr members. + // Initially this field is the number of InputSections that have been added to + // the OutputSection so far. Later on, after a call to assignAddresses, it + // corresponds to the Elf_Shdr member. uint64_t Size = 0; + + // The following fields correspond to Elf_Shdr members. uint64_t Offset = 0; uint64_t LMAOffset = 0; uint64_t Addr = 0; @@ -107,12 +111,12 @@ private: // Used for implementation of --compress-debug-sections option. - std::vector ZDebugHeader; - llvm::SmallVector CompressedData; - - uint32_t getFiller(); -}; - + std::vector ZDebugHeader; + llvm::SmallVector CompressedData; + + uint32_t getFiller(); +}; + int getPriority(StringRef S); // All output sections that are handled by the linker specially are Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -116,13 +116,7 @@ IS->Parent = this; Flags |= IS->Flags; Alignment = std::max(Alignment, IS->Alignment); - - // The actual offsets will be computed by assignAddresses. For now, use - // crude approximation so that it is at least easy for other code to know the - // section order. It is also used to calculate the output section size early - // for compressed debug sections. - IS->OutSecOff = alignTo(Size, IS->Alignment); - this->Size = IS->OutSecOff + IS->getSize(); + IS->OutSecOff = Size++; // If this section contains a table of fixed-size entries, sh_entsize // holds the element size. If it contains elements of different size we @@ -189,6 +183,15 @@ !Name.startswith(".debug_")) return; + // Calculate the section offsets and size pre-compression. + Size = 0; + for (BaseCommand *Cmd : SectionCommands) + if (auto *ISD = dyn_cast(Cmd)) + for (InputSection *IS : ISD->Sections) { + IS->OutSecOff = alignTo(Size, IS->Alignment); + this->Size = IS->OutSecOff + IS->getSize(); + } + // Create a section header. ZDebugHeader.resize(sizeof(Elf_Chdr)); auto *Hdr = reinterpret_cast(ZDebugHeader.data()); Index: test/ELF/linkerscript/unused-synthetic.s =================================================================== --- test/ELF/linkerscript/unused-synthetic.s +++ test/ELF/linkerscript/unused-synthetic.s @@ -13,6 +13,16 @@ # CHECK: .text # CHECK-NEXT: .dynsym +# Test that the size of a removed unused synthetic input section is not added +# to the output section size. Adding a symbol assignment prevents removal of +# the output section, but does not cause the section size to be recomputed. +# RUN: echo "SECTIONS { \ +# RUN: .got.plt : { a_sym = .; *(.got.plt) } \ +# RUN: }" > %t2.script +# RUN: ld.lld -shared -o %t2.so --script %t2.script %t.o +# RUN: llvm-objdump -section-headers %t2.so | FileCheck %s --check-prefix=CHECK2 +# CHECK2: .got.plt 00000000 + .global _start _start: nop