[lld] 8c18719 - [ELF] Expand LMA region if output section alignment introduces padding

Konstantin Schwarz via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 19 02:27:37 PST 2021


Author: Konstantin Schwarz
Date: 2021-11-19T11:27:21+01:00
New Revision: 8c18719bae6f0fe6ff97adad2303c447083e14be

URL: https://github.com/llvm/llvm-project/commit/8c18719bae6f0fe6ff97adad2303c447083e14be
DIFF: https://github.com/llvm/llvm-project/commit/8c18719bae6f0fe6ff97adad2303c447083e14be.diff

LOG: [ELF] Expand LMA region if output section alignment introduces padding

When aligning the start address of an output section introduces a gap between the current dot pointer
and the new aligned address, we were already properly expanding the memory region, if available.

D74286 introduced a new behavior to also align the LMA address if an LMA region is specified.
However, this did not expand the corresponding LMA region.
Now, we also expand the LMA region if it is set.

This fixes PR52510.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D114166

Added: 
    lld/test/ELF/linkerscript/lma-align2.test

Modified: 
    lld/ELF/LinkerScript.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 415afef45a69f..dcc7ebb2a293f 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -976,12 +976,16 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
   // reuse previous lmaOffset; otherwise, reset lmaOffset to 0. This emulates
   // heuristics described in
   // https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html
-  if (sec->lmaExpr)
+  if (sec->lmaExpr) {
     ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
-  else if (MemoryRegion *mr = sec->lmaRegion)
-    ctx->lmaOffset = alignTo(mr->curPos, sec->alignment) - dot;
-  else if (!sameMemRegion || !prevLMARegionIsDefault)
+  } else if (MemoryRegion *mr = sec->lmaRegion) {
+    uint64_t lmaStart = alignTo(mr->curPos, sec->alignment);
+    if (mr->curPos < lmaStart)
+      expandMemoryRegion(mr, lmaStart - mr->curPos, mr->name, sec->name);
+    ctx->lmaOffset = lmaStart - dot;
+  } else if (!sameMemRegion || !prevLMARegionIsDefault) {
     ctx->lmaOffset = 0;
+  }
 
   // Propagate ctx->lmaOffset to the first "non-header" section.
   if (PhdrEntry *l = ctx->outSec->ptLoad)

diff  --git a/lld/test/ELF/linkerscript/lma-align2.test b/lld/test/ELF/linkerscript/lma-align2.test
new file mode 100644
index 0000000000000..2177101ff3747
--- /dev/null
+++ b/lld/test/ELF/linkerscript/lma-align2.test
@@ -0,0 +1,35 @@
+# REQUIRES: x86
+# RUN: echo '.globl _start; _start: ret;' | \
+# RUN:   llvm-mc -filetype=obj -triple=x86_64 - -o %t.o
+# RUN: ld.lld -T %s %t.o -o %t
+# RUN: llvm-readelf -S -l %t | FileCheck %s
+
+# CHECK:      Name         Type     Address          Off    Size   ES Flg Lk Inf Al
+# CHECK-NEXT:              NULL     0000000000000000 000000 000000 00      0   0  0
+# CHECK-NEXT: .text        PROGBITS 0000000008000000 001000 000001 00  AX  0   0  4
+# CHECK-NEXT: .data        PROGBITS 0000000020000000 002000 000006 00  AX  0   0  8
+# CHECK-NEXT: .data2       PROGBITS 000000000800000e 00200e 000008 00  AX  0   0  1
+# CHECK-NEXT: .data3       PROGBITS 0000000020000008 002018 000000 00  AX  0   0  8
+# CHECK-NEXT: .data4       PROGBITS 0000000008000018 002018 000008 00  AX  0   0  1
+
+
+# CHECK:      Type  Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+# CHECK-NEXT: LOAD  0x001000 0x0000000008000000 0x0000000008000000 0x000001 0x000001 R E 0x1000
+# CHECK-NEXT: LOAD  0x002000 0x0000000020000000 0x0000000008000008 0x000006 0x000006 R E 0x1000
+# CHECK-NEXT: LOAD  0x00200e 0x000000000800000e 0x000000000800000e 0x000008 0x000008 R E 0x1000
+# CHECK-NEXT: LOAD  0x002018 0x0000000008000018 0x0000000008000018 0x000008 0x000008 R E 0x1000
+
+MEMORY {
+  CODE (rx) : ORIGIN = 0x08000000, LENGTH = 100K
+  DATA (rw) : ORIGIN = 0x20000000, LENGTH = 100K
+}
+
+SECTIONS {
+  .text : { *(.text) } > CODE
+  ## Aligning the start address of .data to 8 should also increase the location counter of CODE.
+  .data : ALIGN(8) { . += 6; } > DATA AT> CODE
+  .data2 : { . += 8; } > CODE
+  ## Also an empty output section with an alignment requirement increases the location counter.
+  .data3 : ALIGN(8) { . = ALIGN(. != 0 ? 4 : 1); } > DATA AT> CODE
+  .data4 : { . += 8; } > CODE
+}


        


More information about the llvm-commits mailing list