[lld] r316580 - [ELF] - Linkerscript: fix issue with SUBALIGN.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 25 07:50:51 PDT 2017


Author: grimar
Date: Wed Oct 25 07:50:51 2017
New Revision: 316580

URL: http://llvm.org/viewvc/llvm-project?rev=316580&view=rev
Log:
[ELF] - Linkerscript: fix issue with SUBALIGN.

This is PR34886.

SUBALIGN command currently triggers failture if result expression
is zero. Patch fixes the issue, treating zero as 1, what is consistent with
other places and ELF spec it seems.

Patch also adds "is power of 2" check for this and other expressions
returning alignment.

Differential revision: https://reviews.llvm.org/D38846

Modified:
    lld/trunk/ELF/ScriptParser.cpp
    lld/trunk/test/ELF/linkerscript/align.s
    lld/trunk/test/ELF/linkerscript/subalign.s

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=316580&r1=316579&r2=316580&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Wed Oct 25 07:50:51 2017
@@ -642,6 +642,17 @@ void ScriptParser::readSectionAddressTyp
   }
 }
 
+static Expr checkAlignment(Expr E, std::string &Loc) {
+  return [=] {
+    uint64_t Alignment = std::max((uint64_t)1, E().getValue());
+    if (!isPowerOf2_64(Alignment)) {
+      error(Loc + ": alignment must be power of 2");
+      return (uint64_t)1; // Return a dummy value.
+    }
+    return Alignment;
+  };
+}
+
 OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {
   OutputSection *Cmd =
       Script->createOutputSection(OutSec, getCurrentLocation());
@@ -650,12 +661,13 @@ OutputSection *ScriptParser::readOutputS
     readSectionAddressType(Cmd);
   expect(":");
 
+  std::string Location = getCurrentLocation();
   if (consume("AT"))
     Cmd->LMAExpr = readParenExpr();
   if (consume("ALIGN"))
-    Cmd->AlignExpr = readParenExpr();
+    Cmd->AlignExpr = checkAlignment(readParenExpr(), Location);
   if (consume("SUBALIGN"))
-    Cmd->SubalignExpr = readParenExpr();
+    Cmd->SubalignExpr = checkAlignment(readParenExpr(), Location);
 
   // Parse constraints.
   if (consume("ONLY_IF_RO"))
@@ -959,16 +971,16 @@ Expr ScriptParser::readPrimary() {
   if (Tok == "ALIGN") {
     expect("(");
     Expr E = readExpr();
-    if (consume(")"))
-      return [=] {
-        return alignTo(Script->getDot(), std::max((uint64_t)1, E().getValue()));
-      };
+    if (consume(")")) {
+      E = checkAlignment(E, Location);
+      return [=] { return alignTo(Script->getDot(), E().getValue()); };
+    }
     expect(",");
-    Expr E2 = readExpr();
+    Expr E2 = checkAlignment(readExpr(), Location);
     expect(")");
     return [=] {
       ExprValue V = E();
-      V.Alignment = std::max((uint64_t)1, E2().getValue());
+      V.Alignment = E2().getValue();
       return V;
     };
   }

Modified: lld/trunk/test/ELF/linkerscript/align.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/align.s?rev=316580&r1=316579&r2=316580&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/align.s (original)
+++ lld/trunk/test/ELF/linkerscript/align.s Wed Oct 25 07:50:51 2017
@@ -81,6 +81,14 @@
 # RUN: ld.lld -o %t5 --script %t.script %t
 # RUN: llvm-objdump -section-headers %t5 | FileCheck %s -check-prefix=ZERO
 
+## Test we fail gracefuly when alignment value is not a power of 2 (#1).
+# RUN: echo "SECTIONS { . = 0x123; . = ALIGN(0x123, 3); .aaa : { *(.aaa) } }" > %t.script
+# RUN: not ld.lld -o %t6 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR %s
+# ERR: {{.*}}.script:1: alignment must be power of 2
+
+## Test we fail gracefuly when alignment value is not a power of 2 (#2).
+# RUN: echo "SECTIONS { . = 0x123; . = ALIGN(3); .aaa : { *(.aaa) } }" > %t.script
+# RUN: not ld.lld -o %t7 --script %t.script %t 2>&1 | FileCheck -check-prefix=ERR %s
 
 # RUN: echo "SECTIONS {                              \
 # RUN:  . = 0xff8;                                   \

Modified: lld/trunk/test/ELF/linkerscript/subalign.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/subalign.s?rev=316580&r1=316579&r2=316580&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/subalign.s (original)
+++ lld/trunk/test/ELF/linkerscript/subalign.s Wed Oct 25 07:50:51 2017
@@ -22,6 +22,23 @@
 # SUBALIGN:   01000000 00000000 02000000 00000000
 # SUBALIGN:   03000000 00000000 04000000 00000000
 
+## Test we do not assert or crash when dot(.) is used inside SUBALIGN. 
+## ld.bfd does not allow to use dot in such expressions, our behavior is
+## different for simplicity of implementation. Value of dot is undefined.
+# RUN: echo "SECTIONS { . = 0x32; .aaa : SUBALIGN(.) { *(.aaa*) } }" > %t3.script
+# RUN: ld.lld %t1.o --script %t3.script -o %t3 
+# RUN: llvm-objdump -s %t3 > /dev/null
+
+## Test we are able to link with zero alignment, this is consistent with bfd 2.26.1.
+# RUN: echo "SECTIONS { .aaa : SUBALIGN(0) { *(.aaa*) } }" > %t4.script
+# RUN: ld.lld %t1.o --script %t4.script -o %t4
+# RUN: llvm-objdump -s %t4 | FileCheck -check-prefix=SUBALIGN %s
+
+## Test we fail gracefuly when alignment value is not a power of 2.
+# RUN: echo "SECTIONS { .aaa : SUBALIGN(3) { *(.aaa*) } }" > %t5.script
+# RUN: not ld.lld %t1.o --script %t5.script -o %t5 2>&1 | FileCheck -check-prefix=ERR %s
+# ERR: {{.*}}.script:1: alignment must be power of 2
+
 .global _start
 _start:
  nop




More information about the llvm-commits mailing list