See `docs/ELF/linker_script.rst` for the new computation for sh_addr and sh_addralign.
`ALIGN(section_align)` now means: "increase alignment to section_align"
(like yet another input section requirement).
The "start of section .foo changes from 0x11 to 0x20" warning no longer
makes sense. Change it to warn if sh_addr%sh_addralign!=0.
To decrease the alignment from the default max_input_align,
use `.output ALIGN(8) : {}` instead of `.output : ALIGN(8) {}`
See linkerscript/section-address-align.test as an example.
When both an output section address and ALIGN are set (can be seen as an
"undefined behavior" https://sourceware.org/ml/binutils/2020-03/msg00115.html),
lld may align more than GNU ld, but it makes a linker script working
with GNU ld hard to break with lld.
This patch can be considered as restoring part of the behavior before D74736.
Differential Revision: https://reviews.llvm.org/D75724
ctx->outSec = sec;
uint64_t pos = advance(0, 1);
- if (sec->addrExpr && !sec->alignExpr) {
+ if (sec->addrExpr && script->hasSectionsCommand) {
// The alignment is ignored.
ctx->outSec->addr = pos;
} else {
- // If ALIGN is specified, advance sh_addr according to ALIGN and ignore the
- // maximum of input section alignments.
- //
- // When no SECTIONS command is given, sec->alignExpr is set to the maximum
- // of input section alignments.
- uint32_t align =
- sec->alignExpr ? sec->alignExpr().getValue() : ctx->outSec->alignment;
- ctx->outSec->addr = advance(0, align);
+ // ctx->outSec->alignment is the max of ALIGN and the maximum of input
+ // section alignments.
+ ctx->outSec->addr = advance(0, ctx->outSec->alignment);
expandMemoryRegions(ctx->outSec->addr - pos);
}
}
expandMemoryRegion(ctx->memRegion, dot - ctx->memRegion->curPos,
ctx->memRegion->name, sec->name);
- uint64_t oldDot = dot;
switchTo(sec);
- if (sec->addrExpr && oldDot != dot)
- changedSectionAddresses.push_back({sec, oldDot});
ctx->lmaOffset = 0;
auto deleter = std::make_unique<AddressState>();
ctx = deleter.get();
errorOnMissingSection = true;
- changedSectionAddresses.clear();
switchTo(aether);
SymbolAssignmentMap oldValues = getSymbolAssignmentValues(sectionCommands);
// Sections that will be warned/errored by --orphan-handling.
std::vector<const InputSectionBase *> orphanSections;
-
- // Sections whose addresses are not equal to their addrExpr values.
- std::vector<std::pair<const OutputSection *, uint64_t>>
- changedSectionAddresses;
};
extern LinkerScript *script;
}
}
- // If a SECTIONS command is given, addrExpr, if set, is the specified output
- // section address. Warn if the computed value is different from the actual
- // address.
- if (!script->hasSectionsCommand)
- return;
- for (auto changed : script->changedSectionAddresses) {
- const OutputSection *os = changed.first;
- warn("start of section " + os->name + " changes from 0x" +
- utohexstr(changed.second) + " to 0x" + utohexstr(os->addr));
- }
+ // If addrExpr is set, the address may not be a multiple of the alignment.
+ // Warn because this is error-prone.
+ for (BaseCommand *cmd : script->sectionCommands)
+ if (auto *os = dyn_cast<OutputSection>(cmd))
+ if (os->addr % os->alignment != 0)
+ warn("address (0x" + Twine::utohexstr(os->addr) + ") of section " +
+ os->name + " is not a multiple of alignment (" +
+ Twine(os->alignment) + ")");
}
static void finalizeSynthetic(SyntheticSection *sec) {
possible. We reserve the right to make different implementation choices where
it is appropriate for LLD. Intentional deviations will be documented in this
file.
+
+Output section description
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The description of an output section looks like:
+
+::
+
+ section [address] [(type)] : [AT(lma)] [ALIGN(section_align)] [SUBALIGN](subsection_align)] {
+ output-section-command
+ ...
+ } [>region] [AT>lma_region] [:phdr ...] [=fillexp] [,]
+
+Output section address
+----------------------
+
+When an *OutputSection* *S* has ``address``, LLD will set sh_addr to ``address``.
+
+The ELF specification says:
+
+> The value of sh_addr must be congruent to 0, modulo the value of sh_addralign.
+
+The presence of ``address`` can cause the condition unsatisfied. LLD will warn.
+GNU ld from Binutils 2.35 onwards will reduce sh_addralign so that
+sh_addr=0 (modulo sh_addralign).
+
+Output section alignment
+------------------------
+
+sh_addralign of an *OutputSection* *S* is the maximum of
+``ALIGN(section_align)`` and the maximum alignment of the input sections in
+*S*.
+
+When an *OutputSection* *S* has both ``address`` and ``ALIGN(section_align)``,
+GNU ld will set sh_addralign to ``ALIGN(section_align)``.
# RUN: ld.lld -T %s %t.o -o %t 2>&1 | FileCheck --check-prefix=WARN %s --implicit-check-not=warning:
# RUN: llvm-readelf -S -l %t | FileCheck %s
-# WARN: warning: start of section .data changes from 0x11001 to 0x11010
-# WARN: warning: start of section .bss changes from 0x11021 to 0x11040
+# WARN: warning: address (0x11001) of section .data is not a multiple of alignment (32)
+# WARN: warning: address (0x11021) of section .bss is not a multiple of alignment (64)
# 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 0000000000001000 001000 000001 00 AX 0 0 4
# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000011000 002000 000001 00 WA 0 0 16
-# CHECK-NEXT: .data PROGBITS 0000000000011010 002010 000011 00 WA 0 0 32
-# CHECK-NEXT: .bss NOBITS 0000000000011040 002040 000001 00 WA 0 0 64
+# CHECK-NEXT: .data PROGBITS 0000000000011001 002001 000020 00 WA 0 0 32
+# CHECK-NEXT: .bss NOBITS 0000000000011021 002021 000001 00 WA 0 0 64
# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000001 0x000001 R E 0x1000
# CHECK-NEXT: LOAD 0x002000 0x0000000000011000 0x0000000000001010 0x000001 0x000001 RW 0x1000
-# CHECK-NEXT: LOAD 0x002010 0x0000000000011010 0x0000000000001020 0x000011 0x000011 RW 0x1000
-# CHECK-NEXT: LOAD 0x002040 0x0000000000011040 0x0000000000011040 0x000000 0x000001 RW 0x1000
+# CHECK-NEXT: LOAD 0x002001 0x0000000000011001 0x0000000000001020 0x000020 0x000020 RW 0x1000
+# CHECK-NEXT: LOAD 0x002021 0x0000000000011021 0x0000000000011021 0x000000 0x000001 RW 0x1000
MEMORY {
ROM : ORIGIN = 0x1000, LENGTH = 1K
--- /dev/null
+# REQUIRES: x86
+## Test ALIGN when specifying the output section address.
+
+# RUN: echo '.globl _start; _start: ret; \
+# RUN: .data.rel.ro; .balign 8; .byte 0; \
+# RUN: .data; .byte 0; \
+# RUN: .bss; .balign 32; .byte 0' | \
+# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t.o
+# RUN: ld.lld -T %s %t.o -o %t 2>&1 | FileCheck --check-prefix=WARN %s --implicit-check-not=warning:
+# RUN: llvm-readelf -S %t | FileCheck %s
+
+# WARN: warning: address (0x10004) of section .data.rel.ro is not a multiple of alignment (8)
+# WARN: warning: address (0x20008) of section .bss is not a multiple of alignment (32)
+
+# 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 0000000000010000 001000 000001 00 AX 0 0 4
+# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000010004 001004 000005 00 WA 0 0 8
+# CHECK-NEXT: .data PROGBITS 0000000000020000 002000 000001 00 WA 0 0 1
+# CHECK-NEXT: .bss NOBITS 0000000000020008 002001 000019 00 WA 0 0 32
+
+SECTIONS {
+ .text 0x10000 : { *(.text) }
+ ## The output .data.rel.ro starts at 0x10004.
+ ## The input .data.rel.ro starts at 0x10008 and ends at 0x10009.
+ ## sh_size(.data.rel.ro) = 0x10009-0x10004 = 0x5.
+ .data.rel.ro ALIGN(4) : { *(.data.rel.ro) }
+
+ .data 0x20000 : { *(.data) }
+ ## The output .bss starts at 0x20008.
+ ## The input .bss starts at 0x20020 and ends at 0x20021.
+ ## sh_size(.bss) = 0x20021-0x20008 = 0x19.
+ .bss ALIGN(8) : { *(.bss) }
+}
## Test ALIGN and its interaction with explicit output section addresses.
# RUN: echo '.globl _start; _start: ret; .data.rel.ro; .balign 8; .byte 0; .data; .byte 0; \
-# RUN: .section .data2,"aw"; .balign 8; .byte 0; .bss; .balign 32; .byte 0' | \
+# RUN: .section .data2,"aw"; .balign 8; .byte 0; \
+# RUN: .section .data3,"aw"; .balign 32; .byte 0; \
+# RUN: .bss; .balign 32; .byte 0' | \
# RUN: llvm-mc -filetype=obj -triple=aarch64 - -o %t.o
# RUN: ld.lld -T %s %t.o -o %t 2>&1 | FileCheck --check-prefix=WARN %s --implicit-check-not=warning:
# RUN: llvm-readelf -S %t | FileCheck %s
## Check we don't warn in the absence of SECTIONS.
# RUN: ld.lld --fatal-warnings -Ttext=0x10000 %t.o -o /dev/null
-# WARN: warning: start of section .data.rel.ro changes from 0x10004 to 0x10010
-# WARN: warning: start of section .bss changes from 0x20009 to 0x20010
+# WARN: warning: address (0x10004) of section .data.rel.ro is not a multiple of alignment (16)
+# WARN: warning: address (0x20001) of section .data2 is not a multiple of alignment (8)
+# WARN: warning: address (0x20021) of section .bss is not a multiple of alignment (32)
# 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 0000000000010000 010000 000004 00 AX 0 0 4
-# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000010010 010010 000001 00 WA 0 0 16
+# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000010004 010004 000005 00 WA 0 0 16
# CHECK-NEXT: .data PROGBITS 0000000000020000 020000 000001 00 WA 0 0 1
# CHECK-NEXT: .data2 PROGBITS 0000000000020001 020001 000008 00 WA 0 0 8
-# CHECK-NEXT: .bss NOBITS 0000000000020010 020009 000011 00 WA 0 0 32
+# CHECK-NEXT: .data3 PROGBITS 0000000000020020 020020 000001 00 WA 0 0 32
+# CHECK-NEXT: .bss NOBITS 0000000000020021 020021 000020 00 WA 0 0 32
SECTIONS {
.text 0x10000 : { *(.text) }
## The output section address is set without ALIGN. sh_addr is set to Dot, ignoring alignment.
## sh_addralign is the maximum of input section alignments, 8.
.data2 . : { *(.data2) }
+ ## sh_addr is aligned to 32.
+ ## The input section has a larger alignment and is thus preceded by a gap.
+ .data3 : ALIGN(16) { *(.data3) }
## sh_addr is aligned to 16.
## The input section has a larger alignment and is thus preceded by a gap.
.bss . : ALIGN(16) { *(.bss) }