[PATCH] D64476: [LLD][ELF] - Linkerscript: Fix FILL() expressions handling.

George Rimar via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 10 05:05:50 PDT 2019


grimar created this revision.
grimar added reviewers: ruiu, MaskRay.
Herald added subscribers: arichardson, emaste.
Herald added a reviewer: espindola.

D64130 <https://reviews.llvm.org/D64130> introduced a bug described in the following message:
https://reviews.llvm.org/D64130#1571560

The problem can happen with the following script:

  SECTIONS {
    .out : {
  ...
     FILL(0x10101010)
     *(.aaa)
  ...
  }

The current code tries to read `(0x10101010)` as an expression and
does not break when meets `*`, what results in a script parsing error.

In this patch, I verify that `FILL` command's expression always wrapped in `()`.
And at the same time `=<fillexp>` expression can be both wrapped or unwrapped.
I checked it matches to bfd/gold.


https://reviews.llvm.org/D64476

Files:
  ELF/ScriptParser.cpp
  test/ELF/linkerscript/fill.test
  test/ELF/linkerscript/sections-padding.s


Index: test/ELF/linkerscript/sections-padding.s
===================================================================
--- test/ELF/linkerscript/sections-padding.s
+++ test/ELF/linkerscript/sections-padding.s
@@ -7,11 +7,16 @@
 # RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
 # YES: 66000011 22000011 22000011 22000011
 
+# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1100+0x22 }" > %t.script
+# RUN: ld.lld -o %t.out --script %t.script %t
+# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s
+# YES2: 66000011 22000011 22000011 22000011
+
 ## Confirming that address was correct:
 # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99887766 }" > %t.script
 # RUN: ld.lld -o %t.out --script %t.script %t
-# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s
-# YES2: 66998877 66998877 66998877 66998877
+# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES3 %s
+# YES3: 66998877 66998877 66998877 66998877
 
 ## Default padding value is 0x00:
 # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script
@@ -51,7 +56,7 @@
 # RUN: ld.lld -o %t.out --script %t.script %t
 # RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
 
-## Check we report an error if expression value is larger that 32-bits.
+## Check we report an error if expression value is larger than 32-bits.
 # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =(0x11 << 32) }" > %t.script
 # RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 | FileCheck --check-prefix=ERR3 %s
 # ERR3: filler expression result does not fit 32-bit: 0x1100000000
Index: test/ELF/linkerscript/fill.test
===================================================================
--- test/ELF/linkerscript/fill.test
+++ test/ELF/linkerscript/fill.test
@@ -7,6 +7,7 @@
   .out : {
    FILL(0x11111111)
    . += 2;
+   FILL(0x10101010)
    *(.aaa)
    . += 4;
    *(.bbb)
@@ -18,3 +19,7 @@
 
 # CHECK:      Contents of section .out:
 # CHECK-NEXT: 2222aa22 222222bb 22222222 22222222
+
+# RUN: echo 'SECTIONS { .out : { FILL 0x11111111 } }' > %t.script
+# RUN: not ld.lld -o /dev/null --script %t.script 2>&1 | FileCheck %s --check-prefix=ERR
+# ERR: ( expected, but got 0x11111111
\ No newline at end of file
Index: ELF/ScriptParser.cpp
===================================================================
--- ELF/ScriptParser.cpp
+++ ELF/ScriptParser.cpp
@@ -828,7 +828,9 @@
       // We handle the FILL command as an alias for =fillexp section attribute,
       // which is different from what GNU linkers do.
       // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
+      expect("(");
       cmd->filler = readFill();
+      expect(")");
     } else if (tok == "SORT") {
       readSort();
     } else if (tok == "INCLUDE") {
@@ -881,7 +883,14 @@
 // size, while ld.gold always handles it as a 32-bit big-endian number.
 // We are compatible with ld.gold because it's easier to implement.
 std::array<uint8_t, 4> ScriptParser::readFill() {
-  uint64_t value = readExpr()().val;
+  uint64_t value;
+  if (consume("(")) {
+    value = readExpr()().val;
+    expect(")");
+  } else {
+    value = readExpr()().val;
+  }
+
   if (value > UINT32_MAX)
     setError("filler expression result does not fit 32-bit: 0x" +
              Twine::utohexstr(value));


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D64476.208922.patch
Type: text/x-patch
Size: 3269 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190710/14d8d7cc/attachment.bin>


More information about the llvm-commits mailing list