[lld] r320472 - [ELF] Reset OutputSection size prior to processing linker script commands

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 12 03:51:13 PST 2017


Author: jhenderson
Date: Tue Dec 12 03:51:13 2017
New Revision: 320472

URL: http://llvm.org/viewvc/llvm-project?rev=320472&view=rev
Log:
[ELF] Reset OutputSection size prior to processing linker script commands

The size of an OutputSection is calculated early, to aid handling of compressed
debug sections. However, subsequent to this point, unused synthetic sections are
removed. In the event that an OutputSection, from which such an InputSection is
removed, is still required (e.g. because it has a symbol assignment), and no longer
has any InputSections, dot assignments, or BYTE()-family directives, the size
member is never updated when processing the commands. If the removed InputSection
had a non-zero size (such as a .got.plt section), the section ends up with the
wrong size in the output.

The fix is to reset the OutputSection size prior to processing the linker script
commands relating to that OutputSection. This ensures that the size is correct even
in the above situation.

Additionally, to reduce the risk of developers misusing OutputSection Size and
InputSection OutSecOff, they are set to simply the number of InputSections in an
OutputSection, and the corresponding index respectively. We cannot completely
stop using them, due to SHF_LINK_ORDER sections requiring them.

Compressed debug sections also require the full size. This is now calculated in
maybeCompress for these kinds of sections.

Reviewers: ruiu, rafael

Differential Revision: https://reviews.llvm.org/D38361

Modified:
    lld/trunk/ELF/InputSection.h
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
    lld/trunk/test/ELF/linkerscript/unused-synthetic.s

Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=320472&r1=320471&r2=320472&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Tue Dec 12 03:51:13 2017
@@ -318,13 +318,15 @@ public:
 
   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 <class ELFT, class RelTy>
   void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=320472&r1=320471&r2=320472&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Tue Dec 12 03:51:13 2017
@@ -674,6 +674,11 @@ void LinkerScript::assignOffsets(OutputS
   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.

Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=320472&r1=320471&r2=320472&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Tue Dec 12 03:51:13 2017
@@ -116,13 +116,7 @@ void OutputSection::addSection(InputSect
   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 @@ template <class ELFT> void OutputSection
       !Name.startswith(".debug_"))
     return;
 
+  // Calculate the section offsets and size pre-compression.
+  Size = 0;
+  for (BaseCommand *Cmd : SectionCommands)
+    if (auto *ISD = dyn_cast<InputSectionDescription>(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<Elf_Chdr *>(ZDebugHeader.data());

Modified: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=320472&r1=320471&r2=320472&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.h (original)
+++ lld/trunk/ELF/OutputSections.h Tue Dec 12 03:51:13 2017
@@ -71,8 +71,12 @@ public:
   // 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 @@ public:
 
 private:
   // Used for implementation of --compress-debug-sections option.
-  std::vector<uint8_t> ZDebugHeader;
-  llvm::SmallVector<char, 1> CompressedData;
-
-  uint32_t getFiller();
-};
-
+  std::vector<uint8_t> ZDebugHeader;
+  llvm::SmallVector<char, 1> CompressedData;
+
+  uint32_t getFiller();
+};
+
 int getPriority(StringRef S);
 
 // All output sections that are handled by the linker specially are

Modified: lld/trunk/test/ELF/linkerscript/unused-synthetic.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/unused-synthetic.s?rev=320472&r1=320471&r2=320472&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/unused-synthetic.s (original)
+++ lld/trunk/test/ELF/linkerscript/unused-synthetic.s Tue Dec 12 03:51:13 2017
@@ -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




More information about the llvm-commits mailing list