summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/ScriptParser.cpp28
-rw-r--r--lld/test/ELF/linkerscript/align.s8
-rw-r--r--lld/test/ELF/linkerscript/subalign.s17
3 files changed, 45 insertions, 8 deletions
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 5582ce672fb..903be2f503c 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -642,6 +642,17 @@ void ScriptParser::readSectionAddressType(OutputSection *Cmd) {
}
}
+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::readOutputSectionDescription(StringRef OutSec) {
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;
};
}
diff --git a/lld/test/ELF/linkerscript/align.s b/lld/test/ELF/linkerscript/align.s
index 1d70fab45fe..99e7382daa5 100644
--- a/lld/test/ELF/linkerscript/align.s
+++ b/lld/test/ELF/linkerscript/align.s
@@ -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; \
diff --git a/lld/test/ELF/linkerscript/subalign.s b/lld/test/ELF/linkerscript/subalign.s
index 8b441d440b0..0c4c5627db9 100644
--- a/lld/test/ELF/linkerscript/subalign.s
+++ b/lld/test/ELF/linkerscript/subalign.s
@@ -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
OpenPOWER on IntegriCloud