const volatile behaviour change in GCC 7

David Brown david@westcontrol.com
Thu Sep 22 10:17:00 GMT 2016


On 22/09/16 09:23, Sebastian Huber wrote:
> Hello,
> 
> for RTEMS we use linker sets to initialize the system. The following
> code worked up to GCC 6, but no longer in GCC 7:
> 
> typedef void ( *rtems_sysinit_handler )( void );
> 
> typedef struct {
>   rtems_sysinit_handler handler;
> } rtems_sysinit_item;
> 
> rtems_sysinit_item volatile const _Linker_set__Sysinit_begin[0]
> __attribute__((__section__(".rtemsroset." "_Sysinit" ".begin")))
> __attribute__((__used__));
> 
> rtems_sysinit_item volatile const _Linker_set__Sysinit_end[0]
> __attribute__((__section__(".rtemsroset." "_Sysinit" ".end")))
> __attribute__((__used__));
> 
> void rtems_initialize_executive(void)
> {
>   const volatile rtems_sysinit_item *cur = _Linker_set__Sysinit_begin;
>   const volatile rtems_sysinit_item *end = _Linker_set__Sysinit_end;
> 
>   while ( cur != end ) {
>     ( *cur->handler )();
>     ++cur;
>   }
> }
> 

Your trouble is that your two pointers, cur and end, are pointing at
different variables.  Comparing two pointers that are independent (i.e.,
not pointing to parts of the same aggregate object) is undefined - the
compiler can assume that these two external objects could be anywhere in
memory, so there is no way (in pure C) for you to know or care how they
are related.  Therefore it can assume that you will never reach "cur ==
end".

Ideally, you want to tell the compiler that you are dealing with an
array, rather than two independent pointers.  But I am not sure how to
express this without at least a little extra overhead (such as having
the linker generate an "array size" constant that you read along with
the start of the array).  Andrew's MAKEGCCNOTKNOWTHEADDRESS macro will
work, however.

> The corresponding GNU ld linker script section is:
> 
>     .rtemsroset : ALIGN_WITH_INPUT {
>         KEEP (*(SORT(.rtemsroset.*)))
>     } > REGION_RODATA AT > REGION_RODATA_LOAD
> 
> In GCC 7, the compiler deduces that "cur != end" is always true and
> generates an infinite loop.
> 
> Up to GCC 6 the "volatile const" seemed to prevent this optimization. I
> know that this linker set stuff is quite non-standard, but is there a
> way to get this to work again on GCC 7?
> 
> The nice thing with the "type volatile const X[0]..." construct is that
> you can generate arbitrary linker sets via it without a need to edit the
> linker command file and with no storage overhead.
> 



More information about the Gcc mailing list