Skip to content

[ELF] Postpone "unable to move location counter backward" error #66854

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions lld/ELF/LinkerScript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,16 @@ void LinkerScript::expandOutputSection(uint64_t size) {

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

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

SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands);
for (SectionCommand *cmd : sectionCommands) {
Expand Down Expand Up @@ -1494,7 +1502,9 @@ static void checkMemoryRegion(const MemoryRegion *region,
}
}

void LinkerScript::checkMemoryRegions() const {
void LinkerScript::checkFinalScriptConditions() const {
if (backwardDotErr.size())
errorOrWarn(backwardDotErr);
for (const OutputSection *sec : outputSections) {
if (const MemoryRegion *memoryRegion = sec->memRegion)
checkMemoryRegion(memoryRegion, sec, sec->addr);
Expand Down
5 changes: 3 additions & 2 deletions lld/ELF/LinkerScript.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ class LinkerScript final {
// Describe memory region usage.
void printMemoryUsage(raw_ostream &os);

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

// SECTIONS command list.
SmallVector<SectionCommand *, 0> sectionCommands;
Expand All @@ -358,6 +358,7 @@ class LinkerScript final {
bool seenDataAlign = false;
bool seenRelroEnd = false;
bool errorOnMissingSection = false;
std::string backwardDotErr;

// List of section patterns specified with KEEP commands. They will
// be kept even if they are unused and --gc-sections is specified.
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2187,7 +2187,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
for (OutputSection *sec : outputSections)
sec->finalize();

script->checkMemoryRegions();
script->checkFinalScriptConditions();

if (config->emachine == EM_ARM && !config->isLE && config->armBe8) {
addArmInputSectionMappingSymbols();
Expand Down
20 changes: 11 additions & 9 deletions lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,24 @@
# 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 | \
# RUN: FileCheck %s --check-prefix=ERR --implicit-check-not=error:

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

## If we merge adjacent duplicate entries, we will have enough space. Don't report
## a spurious error https://github.com/llvm/llvm-project/issues/66836
# 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
# RUN: ld.lld -z norelro -z max-page-size=4096 -T a.t a.o -o a
# RUN: llvm-readelf -S a | FileCheck %s

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

#--- a.s
.globl _start
Expand Down
2 changes: 1 addition & 1 deletion lld/test/ELF/linkerscript/locationcountererr.test
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t
# RUN: not ld.lld %t --script %s -o /dev/null 2>&1 | FileCheck %s
# CHECK: {{.*}}.test:8: unable to move location counter backward for: .text
# CHECK: {{.*}}.test:8: unable to move location counter (0x2000) backward to 0x10 for section '.text'

SECTIONS {
.text 0x2000 : {
Expand Down