splinkersets01 test assumptions

Kinsey Moore kinsey.moore at oarcorp.com
Wed Feb 17 15:32:56 UTC 2021


On 2021/02/17 00:15, Sebastian Huber wrote:
> On 16/02/2021 22:26, Kinsey Moore wrote:
>> In verifying AArch64/ILP32 on hardware I ran across quite a few alignment issues, some of which were caused by the use of SUBALIGN() in the linker scripts mentioned here:
>> https://devel.rtems.org/ticket/4178 <https://devel.rtems.org/ticket/4178>
>>
>> SUBALIGN() was necessary for two reasons:
>>   * libc sysinit linker sets (this can be fixed in the sysinit handler
>>     struct)
>>   * splinkersets01 could not be made to pass on ILP32 as-is without
>>     SUBALIGN
>>
> In the ld documentation we have:
>
> https://sourceware.org/binutils/docs/ld/Forced-Input-Alignment.html#index-SUBALIGN_0028subsection_005falign_0029
>
> "You can force input section alignment within an output section by using
> SUBALIGN. The value specified overrides any alignment given by input
> sections, whether larger or smaller."
>
> I think the use of SUBALIGN() is a bug and should be removed. Why do you
> want to override the alignment of the input sections?

I agree. The use of SUBALIGN() removes the trailing padding from the input sections used in splinkersets01. The test detects this extra padding as an incorrect number of items/incorrect size. It also removes the trailing padding from _Sysinit sections which was causing libc init to read every other sysinit pointer as NULL.

>> It seems that splinkersets01 makes the assumption that linker sets are aligned to no more than the size of a pointer. For ILP32, this is not the case since AArch64 hardware is very sensitive to misaligned accesses and many structs in linker sections need to be aligned to 8-byte boundaries to avoid throwing exceptions. Some may even need to be aligned to 16-byte boundaries depending on the structure, but this doesn't apply to splinkersets01.
>> The resultant alignment padding causes many assertions in splinkersets01 to fail.
>>
> The linker sets should use the alignment of the item type. This is done
> by defining zero length arrays:

Within a given input section, the items are packed with the proper alignment. Smaller types don't seem to affect the alignment of the linker section within the output section which is why SUBALIGN was used. The alignment of linker sections within an output section defaults to 8 bytes for both ILP32 and LP64 on AArch64.

> #define RTEMS_LINKER_ROSET( set, type ) \
>    type const RTEMS_LINKER_SET_BEGIN( set )[ 0 ] \
>    RTEMS_SECTION( ".rtemsroset." #set ".begin" ) RTEMS_USED; \
>    type const RTEMS_LINKER_SET_END( set )[ 0 ] \
>    RTEMS_SECTION( ".rtemsroset." #set ".end" ) RTEMS_USED
>
> In standard C such arrays are not defined, but GCC does the right thing:
>
> cat test-linkersets.c
> #define RTEMS_USED __attribute__(( __used__ ))
>
> #define RTEMS_SECTION( _section ) __attribute__(( __section__( _section ) ))
>
> #define RTEMS_LINKER_SET_BEGIN( set ) \
>    _Linker_set_##set##_begin
>
> #define RTEMS_LINKER_SET_END( set ) \
>    _Linker_set_##set##_end
>
> #define RTEMS_LINKER_ROSET( set, type ) \
>    type const RTEMS_LINKER_SET_BEGIN( set )[ 0 ] \
>    RTEMS_SECTION( ".rtemsroset." #set ".begin" ) RTEMS_USED; \
>    type const RTEMS_LINKER_SET_END( set )[ 0 ] \
>    RTEMS_SECTION( ".rtemsroset." #set ".end" ) RTEMS_USED
>
> struct s { __attribute__((__aligned__(256))) int i; };
>
> RTEMS_LINKER_ROSET( i, int );
> RTEMS_LINKER_ROSET( ll, long long );
> RTEMS_LINKER_ROSET( s, struct s );
>
> aarch64-rtems6-gcc -O2 -S -o - test-linkersets.c
>          .arch armv8-a
>          .file   "test-linkersets.c"
>          .text
>          .global _Linker_set_s_end
>          .global _Linker_set_s_begin
>          .global _Linker_set_ll_end
>          .global _Linker_set_ll_begin
>          .global _Linker_set_i_end
>          .global _Linker_set_i_begin
>          .section        .rtemsroset.i.begin,"a"
>          .align  3
>          .type   _Linker_set_i_begin, %object
>          .size   _Linker_set_i_begin, 0
> _Linker_set_i_begin:
>          .section        .rtemsroset.i.end,"a"
>          .align  3
>          .type   _Linker_set_i_end, %object
>          .size   _Linker_set_i_end, 0
> _Linker_set_i_end:
>          .section        .rtemsroset.ll.begin,"a"
>          .align  3
>          .type   _Linker_set_ll_begin, %object
>          .size   _Linker_set_ll_begin, 0
> _Linker_set_ll_begin:
>          .section        .rtemsroset.ll.end,"a"
>          .align  3
>          .type   _Linker_set_ll_end, %object
>          .size   _Linker_set_ll_end, 0
> _Linker_set_ll_end:
>          .section        .rtemsroset.s.begin,"a"
>          .align  8
>          .type   _Linker_set_s_begin, %object
>          .size   _Linker_set_s_begin, 0
> _Linker_set_s_begin:
>          .section        .rtemsroset.s.end,"a"
>          .align  8
>          .type   _Linker_set_s_end, %object
>          .size   _Linker_set_s_end, 0
> _Linker_set_s_end:
>          .ident  "GCC: (GNU) 10.2.1 20210205 (RTEMS 6, RSB
> 61dcadee0825867ebe51f9f367430ef75b8fe9c0, Newlib d4a756f)"
>
> aarch64-rtems6-gcc -O2 -S -o - test-linkersets.c -mabi=ilp32
>          .arch armv8-a
>          .file   "test-linkersets.c"
>          .text
>          .global _Linker_set_s_end
>          .global _Linker_set_s_begin
>          .global _Linker_set_ll_end
>          .global _Linker_set_ll_begin
>          .global _Linker_set_i_end
>          .global _Linker_set_i_begin
>          .section        .rtemsroset.i.begin,"a"
>          .align  3
>          .type   _Linker_set_i_begin, %object
>          .size   _Linker_set_i_begin, 0
> _Linker_set_i_begin:
>          .section        .rtemsroset.i.end,"a"
>          .align  3
>          .type   _Linker_set_i_end, %object
>          .size   _Linker_set_i_end, 0
> _Linker_set_i_end:
>          .section        .rtemsroset.ll.begin,"a"
>          .align  3
>          .type   _Linker_set_ll_begin, %object
>          .size   _Linker_set_ll_begin, 0
> _Linker_set_ll_begin:
>          .section        .rtemsroset.ll.end,"a"
>          .align  3
>          .type   _Linker_set_ll_end, %object
>          .size   _Linker_set_ll_end, 0
> _Linker_set_ll_end:
>          .section        .rtemsroset.s.begin,"a"
>          .align  8
>          .type   _Linker_set_s_begin, %object
>          .size   _Linker_set_s_begin, 0
> _Linker_set_s_begin:
>          .section        .rtemsroset.s.end,"a"
>          .align  8
>          .type   _Linker_set_s_end, %object
>          .size   _Linker_set_s_end, 0
> _Linker_set_s_end:
>          .ident  "GCC: (GNU) 10.2.1 20210205 (RTEMS 6, RSB
> 61dcadee0825867ebe51f9f367430ef75b8fe9c0, Newlib d4a756f)"
>>
>> <snip>
>>
> I would remove the SUBALIGN() from the linker script. You can also add a
> new test case for splinkersets01 similar to struct s from above. Then we
> should check if the test fails on aarch64 and why it fails.

The example above actually shows the issue I'm having in _Linker_set_i_begin and _Linker_set_i_end. The alignment expands for the larger struct, but does not shrink for data types smaller than 8 bytes, leaving padding that the test interprets as additional space in the linker set.

I'll work on patches for removal of SUBALIGN and the other accompanying adjustments.

Thanks,
Kinsey


More information about the devel mailing list