GNU ld has a counterintuitive lang_propagate_lma_regions rule.
// .foo's LMA region is propagated to .bar because their VMA region is the same, // and .bar does not have an explicit output section address (addr_tree). .foo : { *(.foo) } >RAM AT> FLASH .bar : { *(.bar) } >RAM // An explicit output section address disables propagation. .foo : { *(.foo) } >RAM AT> FLASH .bar . : { *(.bar) } >RAM
In both cases, lld thinks .foo's LMA region is propagated and
places .bar in the same PT_LOAD, so lld diverges from GNU ld w.r.t. the
second case (lma-align.test).
This patch changes Writer<ELFT>::createPhdrs to disable propagation
(start a new PT_LOAD). A user of the first case can make linker scripts
portable by explicitly specifying AT>. By contrast, there was no
workaround for the old behavior.
This change uncovers another LMA related bug in assignOffsets() where
ctx->lmaOffset = 0; was omitted. It caused a spurious "load address
range overlaps" error for at2.test
The new PT_LOAD rule is complex. For convenience, I listed the origins of some subexpressions:
I 'm struggling to read that boolean expression. Would it be possible to move some of the bits around so that the && is at the end or maybe calculate the more complex ones and name them?
A reorder (untested)
Is there any way to rewrite this in the positive form, we have quite a lot of negatives.
!sec->lmaRegion != !lmaRegion
For example set->lmaRegion == nullptr != lmaRegion == nullptr writing it in that form made it easier to read.