Skip to content

Commit 0de0b6d

Browse files
authored
[ELF] Postpone "unable to move location counter backward" error (#66854)
The size of .ARM.exidx may shrink across `assignAddress` calls. It is possible that the initial iteration has a larger location counter, causing `__code_size = __code_end - .; osec : { . += __code_size; }` to report an error, while the error would have been suppressed for subsequent `assignAddress` iterations. Other sections like .relr.dyn may change sizes across `assignAddress` calls as well. However, their initial size is zero, so it is difficiult to trigger a similar error. Similar to https://reviews.llvm.org/D152170, postpone the error reporting. Fix #66836. While here, add more information to the error message.
1 parent 434907e commit 0de0b6d

File tree

5 files changed

+30
-17
lines changed

5 files changed

+30
-17
lines changed

lld/ELF/LinkerScript.cpp

+14-4
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,16 @@ void LinkerScript::expandOutputSection(uint64_t size) {
169169

170170
void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) {
171171
uint64_t val = e().getValue();
172-
if (val < dot && inSec)
173-
error(loc + ": unable to move location counter backward for: " +
174-
state->outSec->name);
172+
// If val is smaller and we are in an output section, record the error and
173+
// report it if this is the last assignAddresses iteration. dot may be smaller
174+
// if there is another assignAddresses iteration.
175+
if (val < dot && inSec) {
176+
backwardDotErr =
177+
(loc + ": unable to move location counter (0x" + Twine::utohexstr(dot) +
178+
") backward to 0x" + Twine::utohexstr(val) + " for section '" +
179+
state->outSec->name + "'")
180+
.str();
181+
}
175182

176183
// Update to location counter means update to section size.
177184
if (inSec)
@@ -1343,6 +1350,7 @@ const Defined *LinkerScript::assignAddresses() {
13431350
state = &st;
13441351
errorOnMissingSection = true;
13451352
st.outSec = aether;
1353+
backwardDotErr.clear();
13461354

13471355
SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands);
13481356
for (SectionCommand *cmd : sectionCommands) {
@@ -1494,7 +1502,9 @@ static void checkMemoryRegion(const MemoryRegion *region,
14941502
}
14951503
}
14961504

1497-
void LinkerScript::checkMemoryRegions() const {
1505+
void LinkerScript::checkFinalScriptConditions() const {
1506+
if (backwardDotErr.size())
1507+
errorOrWarn(backwardDotErr);
14981508
for (const OutputSection *sec : outputSections) {
14991509
if (const MemoryRegion *memoryRegion = sec->memRegion)
15001510
checkMemoryRegion(memoryRegion, sec, sec->addr);

lld/ELF/LinkerScript.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,8 @@ class LinkerScript final {
345345
// Describe memory region usage.
346346
void printMemoryUsage(raw_ostream &os);
347347

348-
// Verify memory/lma overflows.
349-
void checkMemoryRegions() const;
348+
// Check backward location counter assignment and memory region/LMA overflows.
349+
void checkFinalScriptConditions() const;
350350

351351
// SECTIONS command list.
352352
SmallVector<SectionCommand *, 0> sectionCommands;
@@ -358,6 +358,7 @@ class LinkerScript final {
358358
bool seenDataAlign = false;
359359
bool seenRelroEnd = false;
360360
bool errorOnMissingSection = false;
361+
std::string backwardDotErr;
361362

362363
// List of section patterns specified with KEEP commands. They will
363364
// be kept even if they are unused and --gc-sections is specified.

lld/ELF/Writer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -2187,7 +2187,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
21872187
for (OutputSection *sec : outputSections)
21882188
sec->finalize();
21892189

2190-
script->checkMemoryRegions();
2190+
script->checkFinalScriptConditions();
21912191

21922192
if (config->emachine == EM_ARM && !config->isLE && config->armBe8) {
21932193
addArmInputSectionMappingSymbols();

lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test

+11-9
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@
88
# RUN: not ld.lld -z norelro -z max-page-size=4096 -T a.t a.o -o /dev/null --no-merge-exidx-entries 2>&1 | \
99
# RUN: FileCheck %s --check-prefix=ERR --implicit-check-not=error:
1010

11-
# ERR: error: a.t:14: unable to move location counter backward for: code.unused_space
12-
# ERR-NEXT: error: a.t:9: unable to move location counter backward for: dummy1
13-
# ERR-NEXT: error: a.t:10: unable to move location counter backward for: dummy2
14-
# ERR-NEXT: error: a.t:14: unable to move location counter backward for: code.unused_space
15-
# ERR-NEXT: error: a.t:9: unable to move location counter backward for: dummy1
16-
# ERR-NEXT: error: a.t:10: unable to move location counter backward for: dummy2
17-
# ERR-NEXT: error: a.t:14: unable to move location counter backward for: code.unused_space
11+
# ERR: error: a.t:14: unable to move location counter (0x4104) backward to 0x4070 for section 'code.unused_space'
12+
# ERR-NEXT: error: section '.ARM.exidx' will not fit in region 'CODE': overflowed by 148 bytes
1813
# ERR-NEXT: error: section dummy1 at 0x1000 of size 0xFFFFFFFFFFFFFF6C exceeds available address space
1914
# ERR-NEXT: error: section dummy2 at 0x2000 of size 0xFFFFFFFFFFFFFF6C exceeds available address space
2015
# ERR-NEXT: error: section code.unused_space at 0x4104 of size 0xFFFFFFFFFFFFFF6C exceeds available address space
2116

2217
## If we merge adjacent duplicate entries, we will have enough space. Don't report
2318
## a spurious error https://github.com/llvm/llvm-project/issues/66836
24-
# RUN: not ld.lld -z norelro -z max-page-size=4096 -T a.t a.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
19+
# RUN: ld.lld -z norelro -z max-page-size=4096 -T a.t a.o -o a
20+
# RUN: llvm-readelf -S a | FileCheck %s
2521

26-
# ERR2: error: a.t:14: unable to move location counter backward for: code.unused_space
22+
# CHECK: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
23+
# CHECK-NEXT: [ 0] NULL 00000000 000000 000000 00 0 0 0
24+
# CHECK-NEXT: [ 1] dummy1 NOBITS 00001000 001000 00000c 00 A 0 0 1
25+
# CHECK-NEXT: [ 2] dummy2 NOBITS 00002000 001000 00000c 00 A 0 0 1
26+
# CHECK-NEXT: [ 3] .text PROGBITS 00004000 001000 000054 00 AX 0 0 4
27+
# CHECK-NEXT: [ 4] .ARM.exidx ARM_EXIDX 00004054 001054 000010 00 AL 3 0 4
28+
# CHECK-NEXT: [ 5] code.unused_space NOBITS 00004064 001064 00000c 00 A 0 0 1
2729

2830
#--- a.s
2931
.globl _start

lld/test/ELF/linkerscript/locationcountererr.test

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# REQUIRES: x86
22
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t
33
# RUN: not ld.lld %t --script %s -o /dev/null 2>&1 | FileCheck %s
4-
# CHECK: {{.*}}.test:8: unable to move location counter backward for: .text
4+
# CHECK: {{.*}}.test:8: unable to move location counter (0x2000) backward to 0x10 for section '.text'
55

66
SECTIONS {
77
.text 0x2000 : {

0 commit comments

Comments
 (0)