[lld] r282180 - Don't move orphan sections past assignments.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 22 11:05:49 PDT 2016


Author: rafael
Date: Thu Sep 22 13:05:49 2016
New Revision: 282180

URL: http://llvm.org/viewvc/llvm-project?rev=282180&view=rev
Log:
Don't move orphan sections past assignments.

This fixes a case where we would produce an unaligned PT_LOAD.

Added:
    lld/trunk/test/ELF/linkerscript/orphan-align.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=282180&r1=282179&r2=282180&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Sep 22 13:05:49 2016
@@ -514,6 +514,29 @@ template <class ELFT> void LinkerScript<
   }
 }
 
+// When placing orphan sections, we want to place them after symbol assignments
+// so that an orphan after
+//   begin_foo = .;
+//   foo : { *(foo) }
+//   end_foo = .;
+// doesn't break the intended meaning of the begin/end symbols.
+// We don't want to go over sections since Writer<ELFT>::sortSections is the
+// one in charge of deciding the order of the sections.
+// We don't want to go over alignments, since doing so in
+//  rx_sec : { *(rx_sec) }
+//  . = ALIGN(0x1000);
+//  /* The RW PT_LOAD starts here*/
+//  rw_sec : { *(rw_sec) }
+// would mean that the RW PT_LOAD would become unaligned.
+static bool shouldSkip(const BaseCommand &Cmd) {
+  if (isa<OutputSectionCommand>(Cmd))
+    return false;
+  const auto *Assign = dyn_cast<SymbolAssignment>(&Cmd);
+  if (!Assign)
+    return true;
+  return Assign->Name != ".";
+}
+
 template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
   // Orphan sections are sections present in the input files which
   // are not explicitly placed into the output file by the linker script.
@@ -529,10 +552,10 @@ template <class ELFT> void LinkerScript<
     StringRef Name = Sec->getName();
 
     // Find the last spot where we can insert a command and still get the
-    // correct order.
+    // correct result.
     auto CmdIter = Opt.Commands.begin() + CmdIndex;
     auto E = Opt.Commands.end();
-    while (CmdIter != E && !isa<OutputSectionCommand>(**CmdIter)) {
+    while (CmdIter != E && shouldSkip(**CmdIter)) {
       ++CmdIter;
       ++CmdIndex;
     }
@@ -545,10 +568,13 @@ template <class ELFT> void LinkerScript<
     if (Pos == E) {
       Opt.Commands.insert(CmdIter,
                           llvm::make_unique<OutputSectionCommand>(Name));
-    } else {
-      assert(Pos == CmdIter && "Section order doesn't match the linker script");
+      ++CmdIndex;
+      continue;
     }
-    ++CmdIndex;
+
+    // Continue from where we found it.
+    CmdIndex = (Pos - Opt.Commands.begin()) + 1;
+    continue;
   }
 
   // Assign addresses as instructed by linker script SECTIONS sub-commands.

Added: lld/trunk/test/ELF/linkerscript/orphan-align.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/orphan-align.s?rev=282180&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/orphan-align.s (added)
+++ lld/trunk/test/ELF/linkerscript/orphan-align.s Thu Sep 22 13:05:49 2016
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: echo "SECTIONS { \
+# RUN:         .text : { *(.text) } \
+# RUN:         . = ALIGN(0x1000); \
+# RUN:         .data.rel.ro : { *(.data.rel.ro) } \
+# RUN:       }" \ > %t.script
+# RUN: ld.lld -o %t -T %t.script %t.o -shared
+# RUN: llvm-readobj -l %t | FileCheck %s
+
+
+# Test that the orphan section foo is placed before the ALIGN and so the second
+# PT_LOAD is aligned.
+
+
+# CHECK:      Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x0
+
+# CHECK:      Type: PT_LOAD
+# CHECK-NEXT: Offset: 0x1000
+
+nop
+.section .data.rel.ro, "aw"
+.byte 0
+
+.section foo, "ax"
+nop




More information about the llvm-commits mailing list