[PATCH 1/2] linker_lists: Fix end-marker alignment to prevent padding
Tom Rini
trini at konsulko.com
Mon Mar 23 16:29:10 CET 2026
On Mon, Mar 23, 2026 at 10:56:14AM +0100, Rasmus Villemoes wrote:
> On Sat, Mar 21 2026, Simon Glass <sjg at chromium.org> wrote:
>
> > From: Simon Glass <simon.glass at canonical.com>
> >
> > Change the alignment of end markers in ll_entry_end() and ll_end_decl()
> > from __aligned(4) and __aligned(CONFIG_LINKER_LIST_ALIGN) respectively
> > to __aligned(1).
> >
> > The linker places zero-size end markers at aligned boundaries based on
> > what follows them. When the next list's start marker has a high alignment
> > requirement (e.g., 32 bytes), padding gets inserted before the end
> > marker. This causes the byte span (end - start) to not be an exact
> > multiple of the struct size.
> >
> > The compiler optimises pointer subtraction (end - start) using
> > magic-number multiplication for division. This optimisation only produces
> > correct results when the byte span is an exact multiple of the struct
> > size. With padding, the result is garbage (e.g., -858993444 instead of
> > 15).
> >
> > By using __aligned(1), the end marker is placed immediately after the
> > last entry with no padding, ensuring (end - start) equals exactly (n *
> > sizeof) where n is the number of entries.
>
> So I'm wondering why that is guaranteed. I mean, the linker is placing
> these sections one after another in order
>
>
> 2_foo_2_last_foo size sizeof(struct foo), alignment max(4, alignof(struct foo))
> 2_foo_3 size 0, alignment 4 (1 with your patch)
> 2_bar_1 size 0, alignment CONFIG_LINKER_LIST_ALIGN
> 2_bar_2_first_bar size sizeof(struct bar), alignment max(4, alignof(struct bar))
>
> So clearly the end of last_foo does have 4-byte alignment, yet it is
> observed that the linker sometimes makes 2_foo_3's address coincide with
> 2_bar_1's address?
>
> What I don't understand is that it seems that the linker could place the
> zero-size object 2_foo_3 at any 4-byte aligned address between the end
> of 2_foo_2_last_foo and 2_bar_1. And the same seems to be true when one
> changes it to have even smaller alignment requirement.
>
> So why does an align(1) stop the linker from placing that 0-size section
> at the same address as 2_bar_1, or even force it (as we need) to put it
> at the first possible address, i.e. immediately after last_foo? Unless
> alignment 1 is somehow special-cased to mean "place as early as
> possible", I can't see how this should provide any better guarantees
> than what we already have.
>
> So I don't oppose the patch at all, but I'd really like to understand
> how it actually works.
And as was recently demonstrated in getting device trees to be 8 byte
aligned in linker scripts, you need to be making changes in the linker
script to ensure output alignment matches what you expect and also it's
not always obvious what actually will happen in all cases (when you
haven't been dealing with the nuances of linker scripts for days on
end).
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <https://lists.denx.de/pipermail/u-boot/attachments/20260323/c3c81383/attachment.sig>
More information about the U-Boot
mailing list