[lld] r295458 - Diagnose another case of the location counter moving backwards.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 17 08:26:14 PST 2017


Author: rafael
Date: Fri Feb 17 10:26:13 2017
New Revision: 295458

URL: http://llvm.org/viewvc/llvm-project?rev=295458&view=rev
Log:
Diagnose another case of the location counter moving backwards.

This case should be possible to handle, but it is hard:

* In order to create program headers correctly, we have to scan the
  sections in the order they are in the file.

* To find that order, we have to "execute" the linker script.

* The linker script can contain SIZEOF_HEADERS.

So to support this we have to start with a guess of how many headers
we need (3), run the linker script and try to create the program
headers. If it turns out we need more headers, we run the script again
with a larger SIZEOF_HEADERS.

Also, running the linker script depends on knowing the size of the
sections, so we have to finalize them. But creating the program
headers can change the value stored in some sections, so we have to
split size finalization and content finalization.

Looks like the last part is also needed for range extension thunks, so
we might support this at some point. For now just report an error
instead of producing broken files.

Added:
    lld/trunk/test/ELF/linkerscript/out-of-order.s
Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/LinkerScript.h

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=295458&r1=295457&r2=295458&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Feb 17 10:26:13 2017
@@ -91,24 +91,27 @@ static bool isUnderSysroot(StringRef Pat
   return false;
 }
 
+template <class ELFT> void LinkerScript<ELFT>::setDot(Expr E, bool InSec) {
+  uintX_t Val = E(Dot);
+  if (Val < Dot) {
+    if (InSec)
+      error("unable to move location counter backward for: " + CurOutSec->Name);
+    else
+      error("unable to move location counter backward");
+  }
+  Dot = Val;
+  // Update to location counter means update to section size.
+  if (InSec)
+    CurOutSec->Size = Dot - CurOutSec->Addr;
+}
+
 // Sets value of a symbol. Two kinds of symbols are processed: synthetic
 // symbols, whose value is an offset from beginning of section and regular
 // symbols whose value is absolute.
 template <class ELFT>
 void LinkerScript<ELFT>::assignSymbol(SymbolAssignment *Cmd, bool InSec) {
   if (Cmd->Name == ".") {
-    uintX_t Val = Cmd->Expression(Dot);
-    if (Val < Dot) {
-      if (InSec)
-        error("unable to move location counter backward for: " +
-              CurOutSec->Name);
-      else
-        error("unable to move location counter backward");
-    }
-    Dot = Val;
-    // Update to location counter means update to section size.
-    if (InSec)
-      CurOutSec->Size = Dot - CurOutSec->Addr;
+    setDot(Cmd->Expression, InSec);
     return;
   }
 
@@ -566,6 +569,9 @@ void LinkerScript<ELFT>::assignOffsets(O
   if (!Sec)
     return;
 
+  if (Cmd->AddrExpr && Sec->Flags & SHF_ALLOC)
+    setDot(Cmd->AddrExpr);
+
   // Handle align (e.g. ".foo : ALIGN(16) { ... }").
   if (Cmd->AlignExpr)
     Sec->updateAlignment(Cmd->AlignExpr(0));
@@ -801,8 +807,6 @@ void LinkerScript<ELFT>::assignAddresses
     }
 
     auto *Cmd = cast<OutputSectionCommand>(Base.get());
-    if (Cmd->AddrExpr)
-      Dot = Cmd->AddrExpr(Dot);
     assignOffsets(Cmd);
   }
 

Modified: lld/trunk/ELF/LinkerScript.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.h?rev=295458&r1=295457&r2=295458&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.h (original)
+++ lld/trunk/ELF/LinkerScript.h Fri Feb 17 10:26:13 2017
@@ -278,6 +278,7 @@ private:
   void assignSymbol(SymbolAssignment *Cmd, bool InSec = false);
   void addSymbol(SymbolAssignment *Cmd);
   void computeInputSections(InputSectionDescription *);
+  void setDot(Expr E, bool InSec = false);
 
   void discard(ArrayRef<InputSectionBase<ELFT> *> V);
 

Added: lld/trunk/test/ELF/linkerscript/out-of-order.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/out-of-order.s?rev=295458&view=auto
==============================================================================
--- lld/trunk/test/ELF/linkerscript/out-of-order.s (added)
+++ lld/trunk/test/ELF/linkerscript/out-of-order.s Fri Feb 17 10:26:13 2017
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-linux %s -o %t.o
+# RUN: echo "SECTIONS { .data 0x4000 : { *(.data) } .text 0x2000 : { *(.text) } }" > %t.script
+# RUN: not ld.lld -o %t.so --script %t.script %t.o -shared 2>&1 | FileCheck %s
+
+# CHECK:  error: unable to move location counter backward
+
+.quad 0
+.data
+.quad 0




More information about the llvm-commits mailing list