Skip to content

Commit bb7d2b1

Browse files
author
Georgii Rymar
committed
[LLD][ELF] - Disambiguate "=fillexp" with a primary expression to allow =0x90 /DISCARD/
Fixes https://bugs.llvm.org/show_bug.cgi?id=44903 It is about the following case: ``` SECTIONS { .foo : { *(.foo) } =0x90909090 /DISCARD/ : { *(.bar) } } ``` Here while parsing the fill expression we treated the "/" of "/DISCARD/" as operator. With this change, suggested by Fangrui Song, we do not allow expressions with operators (e.g. "0x1100 + 0x22") that are not wrapped into round brackets. It should not be an issue for users, but helps to resolve parsing ambiguity. Differential revision: https://reviews.llvm.org/D74687
1 parent 981f080 commit bb7d2b1

File tree

2 files changed

+12
-4
lines changed

2 files changed

+12
-4
lines changed

lld/ELF/ScriptParser.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
848848
// We handle the FILL command as an alias for =fillexp section attribute,
849849
// which is different from what GNU linkers do.
850850
// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
851-
expect("(");
851+
if (peek() != "(")
852+
setError("( expected, but got " + peek());
852853
cmd->filler = readFill();
853-
expect(")");
854854
} else if (tok == "SORT") {
855855
readSort();
856856
} else if (tok == "INCLUDE") {
@@ -905,8 +905,11 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
905905
// When reading a hexstring, ld.bfd handles it as a blob of arbitrary
906906
// size, while ld.gold always handles it as a 32-bit big-endian number.
907907
// We are compatible with ld.gold because it's easier to implement.
908+
// Also, we require that expressions with operators must be wrapped into
909+
// round brackets. We did it to resolve the ambiguity when parsing scripts like:
910+
// SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } }
908911
std::array<uint8_t, 4> ScriptParser::readFill() {
909-
uint64_t value = readExpr()().val;
912+
uint64_t value = readPrimary()().val;
910913
if (value > UINT32_MAX)
911914
setError("filler expression result does not fit 32-bit: 0x" +
912915
Twine::utohexstr(value));

lld/test/ELF/linkerscript/sections-padding.s

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# RUN: llvm-objdump -s %t.out | FileCheck --check-prefix=YES %s
88
# YES: 66000011 22000011 22000011 22000011
99

10-
# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1100+0x22 }" > %t.script
10+
# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =(0x1100+0x22) }" > %t.script
1111
# RUN: ld.lld -o %t.out --script %t.script %t
1212
# RUN: llvm-objdump -s %t.out | FileCheck --check-prefix=YES2 %s
1313
# YES2: 66000011 22000011 22000011 22000011
@@ -66,6 +66,11 @@
6666
# RUN: not ld.lld -o /dev/null %t --script %t.script 2>&1 | FileCheck --check-prefix=ERR4 %s
6767
# ERR4: symbol not found: foo
6868

69+
## Check we are able to parse scripts where "/DISCARD/" follows a section fill expression.
70+
# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1122 /DISCARD/ : { *(.text) } }" > %t.script
71+
# RUN: ld.lld -o %t.out --script %t.script %t
72+
# RUN: llvm-objdump -s %t.out | FileCheck --check-prefix=YES %s
73+
6974
.section .mysec.1,"a"
7075
.align 16
7176
.byte 0x66

0 commit comments

Comments
 (0)