diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 68f5240ddc690..1ec796a3bdd99 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -177,11 +177,10 @@ void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) { // 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(); + recordError(loc + ": unable to move location counter (0x" + + Twine::utohexstr(dot) + ") backward to 0x" + + Twine::utohexstr(val) + " for section '" + state->outSec->name + + "'"); } // Update to location counter means update to section size. @@ -1411,7 +1410,7 @@ LinkerScript::assignAddresses() { state = &st; errorOnMissingSection = true; st.outSec = aether; - backwardDotErr.clear(); + recordedErrors.clear(); SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands); for (SectionCommand *cmd : sectionCommands) { @@ -1661,6 +1660,11 @@ void LinkerScript::printMemoryUsage(raw_ostream& os) { } } +void LinkerScript::recordError(const Twine &msg) { + auto &str = recordedErrors.emplace_back(); + msg.toVector(str); +} + static void checkMemoryRegion(const MemoryRegion *region, const OutputSection *osec, uint64_t addr) { uint64_t osecEnd = addr + osec->size; @@ -1673,8 +1677,8 @@ static void checkMemoryRegion(const MemoryRegion *region, } void LinkerScript::checkFinalScriptConditions() const { - if (backwardDotErr.size()) - errorOrWarn(backwardDotErr); + for (StringRef err : recordedErrors) + errorOrWarn(err); for (const OutputSection *sec : outputSections) { if (const MemoryRegion *memoryRegion = sec->memRegion) checkMemoryRegion(memoryRegion, sec, sec->addr); diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index 36feab36e26ba..db26d026a00ba 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -350,6 +350,11 @@ class LinkerScript final { // Describe memory region usage. void printMemoryUsage(raw_ostream &os); + // Record a pending error during an assignAddresses invocation. + // assignAddresses is executed more than once. Therefore, lld::error should be + // avoided to not report duplicate errors. + void recordError(const Twine &msg); + // Check backward location counter assignment and memory region/LMA overflows. void checkFinalScriptConditions() const; @@ -375,7 +380,7 @@ class LinkerScript final { bool seenDataAlign = false; bool seenRelroEnd = false; bool errorOnMissingSection = false; - std::string backwardDotErr; + SmallVector, 0> recordedErrors; // List of section patterns specified with KEEP commands. They will // be kept even if they are unused and --gc-sections is specified. diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index f90ce6fa74075..db46263115242 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -158,7 +158,8 @@ static void moveAbsRight(ExprValue &a, ExprValue &b) { if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute())) std::swap(a, b); if (!b.isAbsolute()) - error(a.loc + ": at least one side of the expression must be absolute"); + script->recordError( + a.loc + ": at least one side of the expression must be absolute"); } static ExprValue add(ExprValue a, ExprValue b) { @@ -1384,7 +1385,7 @@ StringRef ScriptParser::readParenLiteral() { static void checkIfExists(const OutputSection &osec, StringRef location) { if (osec.location.empty() && script->errorOnMissingSection) - error(location + ": undefined section " + osec.name); + script->recordError(location + ": undefined section " + osec.name); } static bool isValidSymbolName(StringRef s) { diff --git a/lld/test/ELF/linkerscript/addr.test b/lld/test/ELF/linkerscript/addr.test index c997525e3dc3f..53466dda26791 100644 --- a/lld/test/ELF/linkerscript/addr.test +++ b/lld/test/ELF/linkerscript/addr.test @@ -13,13 +13,11 @@ # CHECK-NEXT: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 1 x2 # CHECK-NEXT: 0000000000001000 0 NOTYPE GLOBAL DEFAULT 1 x3 -## TODO Fix duplicate errors # RUN: not ld.lld a.o -T absent.lds 2>&1 | FileCheck %s --check-prefix=ABSENT --implicit-check-not=error: -# ABSENT-COUNT-2: error: absent.lds:3: undefined section .aaa +# ABSENT: error: absent.lds:3: undefined section .aaa -## TODO Fix duplicate errors # RUN: not ld.lld a.o -T absolute.lds 2>&1 | FileCheck %s --check-prefix=ABSOLUTE --implicit-check-not=error: -# ABSOLUTE-COUNT-4: error: absolute.lds:2: at least one side of the expression must be absolute +# ABSOLUTE: error: absolute.lds:2: at least one side of the expression must be absolute #--- a.s .globl _start diff --git a/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test b/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test index 791a9ae178fa9..2ce35494ca148 100644 --- a/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test +++ b/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test @@ -8,7 +8,9 @@ # 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 (0x4104) backward to 0x4070 for section 'code.unused_space' +# ERR: error: a.t:9: unable to move location counter (0x1000) backward to 0xf6c for section 'dummy1' +# ERR-NEXT: error: a.t:10: unable to move location counter (0x2000) backward to 0x1f6c for section 'dummy2' +# ERR-NEXT: 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