[lld] 0de0b6d - [ELF] Postpone "unable to move location counter backward" error (#66854)

via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 20 09:06:48 PDT 2023


Author: Fangrui Song
Date: 2023-09-20T09:06:45-07:00
New Revision: 0de0b6dded4752040350feb9c81415d82478d065

URL: https://github.com/llvm/llvm-project/commit/0de0b6dded4752040350feb9c81415d82478d065
DIFF: https://github.com/llvm/llvm-project/commit/0de0b6dded4752040350feb9c81415d82478d065.diff

LOG: [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.

Added: 
    

Modified: 
    lld/ELF/LinkerScript.cpp
    lld/ELF/LinkerScript.h
    lld/ELF/Writer.cpp
    lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test
    lld/test/ELF/linkerscript/locationcountererr.test

Removed: 
    


################################################################################
diff  --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 943fd865ae0c15c..df091613dc0a144 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -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)
@@ -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) {
@@ -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);

diff  --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 89780bb60f48244..18eaf58b785e370 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -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;
@@ -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.

diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 40f7d7981d9d441..d6adc4ff3d644db 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -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();

diff  --git a/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test b/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test
index 4dd7ae05d067416..791a9ae178fa94a 100644
--- a/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test
+++ b/lld/test/ELF/linkerscript/locationcountererr-arm-exidx.test
@@ -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

diff  --git a/lld/test/ELF/linkerscript/locationcountererr.test b/lld/test/ELF/linkerscript/locationcountererr.test
index 086bfeba1e3d455..2ab6d7a3ce2cbec 100644
--- a/lld/test/ELF/linkerscript/locationcountererr.test
+++ b/lld/test/ELF/linkerscript/locationcountererr.test
@@ -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 : {


        


More information about the llvm-commits mailing list