[lld] r286837 - Fix program header propagation.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 14 07:39:38 PST 2016


Author: rafael
Date: Mon Nov 14 09:39:38 2016
New Revision: 286837

URL: http://llvm.org/viewvc/llvm-project?rev=286837&view=rev
Log:
Fix program header propagation.

Propagate program headers by walking the commands, not the
sections. This allows us to propagate program headers even from
sections that don't end up in the output.

Fixes pr30997.

Added:
    lld/trunk/test/ELF/linkerscript/Inputs/implicit-program-header.script
    lld/trunk/test/ELF/linkerscript/implicit-program-header.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=286837&r1=286836&r2=286837&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Mon Nov 14 09:39:38 2016
@@ -563,6 +563,35 @@ template <class ELFT> void LinkerScript<
     auto *OutSec = make<OutputSection<ELFT>>(Cmd->Name, Type, Flags);
     OutputSections->push_back(OutSec);
   }
+}
+
+template <class ELFT> void LinkerScript<ELFT>::adjustSectionsAfterSorting() {
+  placeOrphanSections();
+
+  // If output section command doesn't specify any segments,
+  // and we haven't previously assigned any section to segment,
+  // then we simply assign section to the very first load segment.
+  // Below is an example of such linker script:
+  // PHDRS { seg PT_LOAD; }
+  // SECTIONS { .aaa : { *(.aaa) } }
+  std::vector<StringRef> DefPhdrs;
+  auto FirstPtLoad =
+      std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(),
+                   [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; });
+  if (FirstPtLoad != Opt.PhdrsCommands.end())
+    DefPhdrs.push_back(FirstPtLoad->Name);
+
+  // Walk the commands and propagate the program headers to commands that don't
+  // explicitly specify them.
+  for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
+    auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
+    if (!Cmd)
+      continue;
+    if (Cmd->Phdrs.empty())
+      Cmd->Phdrs = DefPhdrs;
+    else
+      DefPhdrs = Cmd->Phdrs;
+  }
 
   removeEmptyCommands();
 }
@@ -630,8 +659,6 @@ void LinkerScript<ELFT>::placeOrphanSect
 
 template <class ELFT>
 void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
-  placeOrphanSections();
-
   // Assign addresses as instructed by linker script SECTIONS sub-commands.
   Dot = 0;
 
@@ -711,7 +738,6 @@ std::vector<PhdrEntry<ELFT>> LinkerScrip
 
   // Process PHDRS and FILEHDR keywords because they are not
   // real output sections and cannot be added in the following loop.
-  std::vector<size_t> DefPhdrIds;
   for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) {
     Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
     PhdrEntry<ELFT> &Phdr = Ret.back();
@@ -725,15 +751,6 @@ std::vector<PhdrEntry<ELFT>> LinkerScrip
       Phdr.H.p_paddr = Cmd.LMAExpr(0);
       Phdr.HasLMA = true;
     }
-
-    // If output section command doesn't specify any segments,
-    // and we haven't previously assigned any section to segment,
-    // then we simply assign section to the very first load segment.
-    // Below is an example of such linker script:
-    // PHDRS { seg PT_LOAD; }
-    // SECTIONS { .aaa : { *(.aaa) } }
-    if (DefPhdrIds.empty() && Phdr.H.p_type == PT_LOAD)
-      DefPhdrIds.push_back(Ret.size() - 1);
   }
 
   // Add output sections to program headers.
@@ -741,17 +758,12 @@ std::vector<PhdrEntry<ELFT>> LinkerScrip
     if (!(Sec->Flags & SHF_ALLOC))
       break;
 
-    std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName());
-    if (PhdrIds.empty())
-      PhdrIds = std::move(DefPhdrIds);
-
     // Assign headers specified by linker script
-    for (size_t Id : PhdrIds) {
+    for (size_t Id : getPhdrIndices(Sec->getName())) {
       Ret[Id].add(Sec);
       if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
         Ret[Id].H.p_flags |= Sec->getPhdrFlags();
     }
-    DefPhdrIds = std::move(PhdrIds);
   }
   return Ret;
 }

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=286837&r1=286836&r2=286837&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Mon Nov 14 09:39:38 2016
@@ -221,6 +221,7 @@ public:
   void createSections(OutputSectionFactory<ELFT> &Factory);
   void removeEmptyCommands();
   void adjustSectionsBeforeSorting();
+  void adjustSectionsAfterSorting();
 
   std::vector<PhdrEntry<ELFT>> createPhdrs();
   bool ignoreInterpSection();

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=286837&r1=286836&r2=286837&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Nov 14 09:39:38 2016
@@ -856,6 +856,8 @@ template <class ELFT> void Writer<ELFT>:
     std::rotate(BestPos, NonScriptI, NonScriptI + 1);
     ++NonScriptI;
   }
+
+  Script<ELFT>::X->adjustSectionsAfterSorting();
 }
 
 // Create output section objects and add them to OutputSections.

Added: lld/trunk/test/ELF/linkerscript/Inputs/implicit-program-header.script
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/Inputs/implicit-program-header.script?rev=286837&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/Inputs/implicit-program-header.script (added)
+++ lld/trunk/test/ELF/linkerscript/Inputs/implicit-program-header.script Mon Nov 14 09:39:38 2016
@@ -0,0 +1,12 @@
+PHDRS
+{
+	ph_write PT_LOAD FLAGS(2);
+	ph_exec  PT_LOAD FLAGS(1);
+}
+
+SECTIONS
+{
+  .bar : { *(.bar) } : ph_exec
+  .foo : { *(.foo) }
+  .text : { *(.text) } : ph_write
+}

Added: lld/trunk/test/ELF/linkerscript/implicit-program-header.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/implicit-program-header.s?rev=286837&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/implicit-program-header.s (added)
+++ lld/trunk/test/ELF/linkerscript/implicit-program-header.s Mon Nov 14 09:39:38 2016
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -o %t1 --script %S/Inputs/implicit-program-header.script  \
+# RUN:   %t.o -shared
+# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s
+
+# CHECK:      Segment Sections...
+# CHECK-NEXT:   00     .text .dynsym .hash .dynstr .dynamic
+# CHECK-NEXT:   01     .foo
+
+.quad 0
+.section .foo,"ax"
+.quad 0




More information about the llvm-commits mailing list