Skip to content

Commit

Permalink
[ELF] Expand LMA region if output section alignment introduces padding
Browse files Browse the repository at this point in the history
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
  • Loading branch information
konstantinschwarz committed Nov 19, 2021
1 parent 6259016 commit 8c18719
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
12 changes: 8 additions & 4 deletions lld/ELF/LinkerScript.cpp
Expand Up @@ -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)
Expand Down
35 changes: 35 additions & 0 deletions 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
}

0 comments on commit 8c18719

Please sign in to comment.