mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 01:58:44 +08:00
[ELF] Propagate LMA offset to sections with neither AT() nor AT>
Fixes https://bugs.llvm.org/show_bug.cgi?id=45313
Also fixes linkerscript/{at4.s,overlay.test} LMA address issues exposed by
011b785505.
Related: D74297
This patch improves emulation of GNU ld's heuristics on the difference
between the LMA and the VMA:
https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html#Output-Section-LMA
New test linkerscript/lma-offset.s (based on at4.s) demonstrates some behaviors.
Reviewed By: psmith
Differential Revision: https://reviews.llvm.org/D76995
This commit is contained in:
@@ -833,6 +833,7 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
|
||||
if (!(sec->flags & SHF_ALLOC))
|
||||
dot = 0;
|
||||
|
||||
bool prevLMARegionIsDefault = ctx->lmaRegion == nullptr;
|
||||
ctx->memRegion = sec->memRegion;
|
||||
ctx->lmaRegion = sec->lmaRegion;
|
||||
if (ctx->memRegion)
|
||||
@@ -851,19 +852,19 @@ void LinkerScript::assignOffsets(OutputSection *sec) {
|
||||
|
||||
switchTo(sec);
|
||||
|
||||
ctx->lmaOffset = 0;
|
||||
|
||||
// ctx->lmaOffset is LMA minus VMA. If LMA is explicitly specified via AT() or
|
||||
// AT>, recompute ctx->lmaOffset; otherwise, if both previous/current LMA
|
||||
// region is the default, 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)
|
||||
ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
|
||||
if (MemoryRegion *mr = sec->lmaRegion)
|
||||
else if (MemoryRegion *mr = sec->lmaRegion)
|
||||
ctx->lmaOffset = alignTo(mr->curPos, sec->alignment) - dot;
|
||||
else if (!prevLMARegionIsDefault)
|
||||
ctx->lmaOffset = 0;
|
||||
|
||||
// If neither AT nor AT> is specified for an allocatable section, the linker
|
||||
// will set the LMA such that the difference between VMA and LMA for the
|
||||
// section is the same as the preceding output section in the same region
|
||||
// https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
|
||||
// This, however, should only be done by the first "non-header" section
|
||||
// in the segment.
|
||||
// Propagate ctx->lmaOffset to the first "non-header" section.
|
||||
if (PhdrEntry *l = ctx->outSec->ptLoad)
|
||||
if (sec == findFirstSection(l))
|
||||
l->lmaOffset = ctx->lmaOffset;
|
||||
|
||||
Reference in New Issue
Block a user