[PATCH 1/2] linker_lists: Fix end-marker alignment to prevent padding
Rasmus Villemoes
ravi at prevas.dk
Mon Mar 23 10:56:14 CET 2026
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.
Rasmus
More information about the U-Boot
mailing list