Commit 6b3c5e8b authored by Andy Ross's avatar Andy Ross Committed by Anas Nashif
Browse files

x86 link: Specify ALIGN_WITH_INPUT for XIP data sections

Binutils ld has an annoying misfeature (apparently a regression from a
few years ago) that alignment directives (and alignment specifiers on
symbols) apply only to the runtime addresses and not, apparently, to
the load address region specified with the "AT>" syntax.  The net
result is that by default the LMA output ends up too small for the
addresses generated in RAM.  See here for some details:

    https://sourceware.org/ml/binutils/2013-06/msg00246.html
    https://sourceware.org/ml/binutils/2014-01/msg00350.html



The required workaround/fix is that AFAICT any section which can have
inherit a separate VMA vs. LMA from a previous section must specify an
"ALIGN_WITH_INPUT" attribute.  Otherwise the sections will get out of
sync and the XIP data will be wrong at runtime.

No, I don't know why this isn't the default behavior.

A further complexity is that this feature only works as advertised
when the section is declared with the "AT> region" syntax after the
block and not "AT(address)" in the header.  If you use the header
syntax (with or without ALIGN_WITH_INPUT), ld appears to DOUBLE-apply
padding and the LMA ends up to big.  This is almost certainly a
binutils bug, but it's trivial to work around (and the working syntax
is actually cleaner) so we adjust the usage here.

Note finally that this patch includes an effective reversion of commit
d82e9dd9 ("x86: HACK force alignment for _k_task_list section"), which
was an earlier workaround for what seems to be the same issue.

Jira: ZEP-955

Change-Id: I2accd92901cb61fb546658b87d6752c1cd14de3a
Signed-off-by: default avatarAndy Ross <andrew.j.ross@intel.com>
parent 72e5a39b
Loading
Loading
Loading
Loading
+14 −18
Original line number Diff line number Diff line
@@ -158,11 +158,7 @@ SECTIONS {

	GROUP_START(RAMABLE_REGION)

#if defined(CONFIG_XIP)
	SECTION_AT_PROLOGUE(_DATA_SECTION_NAME,,,_DATA_IN_ROM) {
#else
	SECTION_PROLOGUE(_DATA_SECTION_NAME,,) {
#endif
	SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) {

/* when XIP, .text is in ROM, but vector table must be at start of .data */

@@ -171,14 +167,14 @@ SECTIONS {
		*(.data)
		*(".data.*")

	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE(initlevel, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(initlevel, (OPTIONAL),)
	{
		DEVICE_INIT_SECTIONS()
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
SECTION_DATA_PROLOGUE (_k_task_list, (OPTIONAL),)
	{
		_k_task_list_start = .;
			*(._k_task_list.public.*)
@@ -187,9 +183,9 @@ SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
			*(._k_task_list.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_list*")))
		_k_task_list_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_task_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_task_ptr, (OPTIONAL),)
	{
		_k_task_ptr_start = .;
			*(._k_task_ptr.public.*)
@@ -197,33 +193,33 @@ SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
			*(._k_task_ptr.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
		_k_task_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
	{
		_k_pipe_ptr_start = .;
			*(._k_pipe_ptr.public.*)
			*(._k_pipe_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_pipe_ptr*")))
		_k_pipe_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_mem_map_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_mem_map_ptr, (OPTIONAL),)
	{
		_k_mem_map_ptr_start = .;
			*(._k_mem_map_ptr.public.*)
			*(._k_mem_map_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_mem_map_ptr*")))
		_k_mem_map_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE(_k_event_list, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_event_list, (OPTIONAL),)
	{
		_k_event_list_start = .;
			*(._k_event_list.event.*)
		KEEP(*(SORT_BY_NAME("._k_event_list*")))
		_k_event_list_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	__data_ram_end = .;

+18 −22
Original line number Diff line number Diff line
@@ -181,24 +181,20 @@ SECTIONS

    GROUP_START(RAMABLE_REGION)

#if defined(CONFIG_XIP)
    SECTION_AT_PROLOGUE(_DATA_SECTION_NAME,,,_DATA_IN_ROM)
#else
    SECTION_PROLOGUE(_DATA_SECTION_NAME,,)
#endif
    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
	{
	_image_ram_start = .;
	__data_ram_start = .;
	*(.data)
	*(".data.*")
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (initlevel, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (initlevel, (OPTIONAL),)
	{
		DEVICE_INIT_SECTIONS()
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_task_list, (OPTIONAL),)
	{
		_k_task_list_start = .;
			*(._k_task_list.public.*)
@@ -207,9 +203,9 @@ SECTIONS
			*(._k_task_list.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_list*")))
		_k_task_list_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_task_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_task_ptr, (OPTIONAL),)
	{
		_k_task_ptr_start = .;
			*(._k_task_ptr.public.*)
@@ -217,35 +213,35 @@ SECTIONS
			*(._k_task_ptr.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
		_k_task_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_pipe_ptr, (OPTIONAL),)
	{
		_k_pipe_ptr_start = .;
			*(._k_pipe_ptr.public.*)
			*(._k_pipe_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_pipe_ptr*")))
		_k_pipe_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE (_k_mem_map_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE (_k_mem_map_ptr, (OPTIONAL),)
	{
		_k_mem_map_ptr_start = .;
			*(._k_mem_map_ptr.public.*)
			*(._k_mem_map_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_mem_map_ptr*")))
		_k_mem_map_ptr_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE(_k_event_list, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_event_list, (OPTIONAL),)
	{
		_k_event_list_start = .;
			*(._k_event_list.event.*)
		KEEP(*(SORT_BY_NAME("._k_event_list*")))
		_k_event_list_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

	SECTION_PROLOGUE(_k_memory_pool, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_memory_pool, (OPTIONAL),)
	{
		*(._k_memory_pool.struct*)
		KEEP(*(SORT_BY_NAME("._k_memory_pool.struct*")))
@@ -254,12 +250,12 @@ SECTIONS
		*(._k_memory_pool.*)
		KEEP(*(SORT_BY_NAME("._k_memory_pool*")))
		_k_mem_pool_end = .;
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)


    __data_ram_end = .;

    SECTION_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
    SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
	{
        /*
         * For performance, BSS section is assumed to be 4 byte aligned and
@@ -275,7 +271,7 @@ SECTIONS
         * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
		 */
	__bss_end = ALIGN(4);
	} GROUP_LINK_IN(RAMABLE_REGION)
	} GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)

    SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),)
        {
+18 −18
Original line number Diff line number Diff line
@@ -176,7 +176,7 @@ SECTIONS
     * This is code not data, but we need this copied just like XIP data
     */

    SECTION_AT_PROLOGUE(_EXCEPTION_SECTION_NAME,,, __data_rom_start)
    SECTION_DATA_PROLOGUE(_EXCEPTION_SECTION_NAME,,)
        {
            _image_ram_start = .;
            __data_ram_start = .;
@@ -184,18 +184,18 @@ SECTIONS
            KEEP(*(".exception.entry.*"))
            *(".exception.other.*")

        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)
#endif

    SECTION_PROLOGUE(initlevel, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(initlevel, (OPTIONAL),)
        {
#ifndef CONFIG_XIP
        _image_ram_start = .;
#endif
                DEVICE_INIT_SECTIONS()
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_k_task_list, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(_k_task_list, (OPTIONAL),)
        {
                _k_task_list_start = .;
                        *(._k_task_list.public.*)
@@ -204,9 +204,9 @@ SECTIONS
                        *(._k_task_list.idle.*)
                KEEP(*(SORT_BY_NAME("._k_task_list*")))
                _k_task_list_end = .;
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_k_task_ptr, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(_k_task_ptr, (OPTIONAL),)
        {
                _k_task_ptr_start = .;
                        *(._k_task_ptr.public.*)
@@ -214,35 +214,35 @@ SECTIONS
                        *(._k_task_ptr.idle.*)
                KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
                _k_task_ptr_end = .;
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_k_pipe_ptr, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(_k_pipe_ptr, (OPTIONAL),)
        {
                _k_pipe_ptr_start = .;
                        *(._k_pipe_ptr.public.*)
                        *(._k_pipe_ptr.private.*)
                KEEP(*(SORT_BY_NAME("._k_pipe_ptr*")))
                _k_pipe_ptr_end = .;
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_k_mem_map_ptr, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(_k_mem_map_ptr, (OPTIONAL),)
        {
                _k_mem_map_ptr_start = .;
                        *(._k_mem_map_ptr.public.*)
                        *(._k_mem_map_ptr.private.*)
                KEEP(*(SORT_BY_NAME("._k_mem_map_ptr*")))
                _k_mem_map_ptr_end = .;
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_k_event_list, (OPTIONAL),)
    SECTION_DATA_PROLOGUE(_k_event_list, (OPTIONAL),)
        {
                _k_event_list_start = .;
                        *(._k_event_list.event.*)
                KEEP(*(SORT_BY_NAME("._k_event_list*")))
                _k_event_list_end = .;
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    SECTION_PROLOGUE(_DATA_SECTION_NAME,,)
    SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,)
        {

        KEEP(*(.isr_irq*))
@@ -279,11 +279,11 @@ SECTIONS
        *(.sdata .sdata.* .gnu.linkonce.s.*)
        *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)

        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION)

    __data_ram_end = .;

    SECTION_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
	SECTION_DATA_PROLOGUE(_BSS_SECTION_NAME,(NOLOAD),)
        {
        /*
         * For performance, BSS section is assumed to be 4 byte aligned and
@@ -301,7 +301,7 @@ SECTIONS
         * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes.
                 */
        __bss_end = ALIGN(4);
        } GROUP_LINK_IN(RAMABLE_REGION)
        } GROUP_DATA_LINK_IN(RAMABLE_REGION, RAMABLE_REGION)

    SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),)
        {
+16 −20
Original line number Diff line number Diff line
@@ -139,11 +139,7 @@ SECTIONS
	/* RAM */
	GROUP_START(RAM)

#if defined(CONFIG_XIP)
	SECTION_AT_PROLOGUE(_DATA_SECTION_NAME, (OPTIONAL), , __data_rom_start)
#else
	SECTION_PROLOGUE(_DATA_SECTION_NAME, (OPTIONAL),)
#endif
	SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME, (OPTIONAL),)
	{
	KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE)
	_image_ram_start = .;
@@ -151,15 +147,15 @@ SECTIONS
	*(.data)
	*(".data.*")
	. = ALIGN(4);
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(initlevel, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(initlevel, (OPTIONAL),)
	{
		DEVICE_INIT_SECTIONS()
		KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE)
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_task_list, ALIGN(4), ALIGN(4))
	SECTION_DATA_PROLOGUE(_k_task_list, (OPTIONAL),)
	{
		_k_task_list_start = .;
			*(._k_task_list.public.*)
@@ -168,9 +164,9 @@ SECTIONS
			*(._k_task_list.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_list*")))
		_k_task_list_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_task_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_task_ptr, (OPTIONAL),)
	{
		_k_task_ptr_start = .;
			*(._k_task_ptr.public.*)
@@ -178,35 +174,35 @@ SECTIONS
			*(._k_task_ptr.idle.*)
		KEEP(*(SORT_BY_NAME("._k_task_ptr*")))
		_k_task_ptr_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_pipe_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_pipe_ptr, (OPTIONAL),)
	{
		_k_pipe_ptr_start = .;
			*(._k_pipe_ptr.public.*)
			*(._k_pipe_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_pipe_ptr*")))
		_k_pipe_ptr_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_mem_map_ptr, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_mem_map_ptr, (OPTIONAL),)
	{
		_k_mem_map_ptr_start = .;
			*(._k_mem_map_ptr.public.*)
			*(._k_mem_map_ptr.private.*)
		KEEP(*(SORT_BY_NAME("._k_mem_map_ptr*")))
		_k_mem_map_ptr_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_event_list, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_event_list, (OPTIONAL),)
	{
		_k_event_list_start = .;
			*(._k_event_list.event.*)
		KEEP(*(SORT_BY_NAME("._k_event_list*")))
		_k_event_list_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	SECTION_PROLOGUE(_k_memory_pool, (OPTIONAL),)
	SECTION_DATA_PROLOGUE(_k_memory_pool, (OPTIONAL),)
	{
		*(._k_memory_pool.struct*)
		KEEP(*(SORT_BY_NAME("._k_memory_pool.struct*")))
@@ -215,7 +211,7 @@ SECTIONS
		*(._k_memory_pool.*)
		KEEP(*(SORT_BY_NAME("._k_memory_pool*")))
		_k_mem_pool_end = .;
	} GROUP_LINK_IN(RAM)
	} GROUP_DATA_LINK_IN(RAM, ROM)

	__data_ram_end = .;

+28 −6
Original line number Diff line number Diff line
@@ -58,6 +58,23 @@
 */
#define GROUP_LINK_IN(where) > where

/*
 * As GROUP_LINK_IN(), but takes a second argument indicating the
 * memory region (e.g. "ROM") for the load address.  Used for
 * initialized data sections that on XIP platforms must be copied at
 * startup.
 *
 * And, because output directives in GNU ld are "sticky", this must
 * also be used on the first section *after* such an initialized data
 * section, specifying the same memory region (e.g. "RAM") for both
 * vregion and lregion.
 */
#ifdef CONFIG_XIP
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT> lregion
#else
#define GROUP_DATA_LINK_IN(vregion, lregion) > vregion
#endif

/*
 * The GROUP_FOLLOWS_AT() macro is located at the end of the section
 * and indicates that the section does not specify an address at which
@@ -77,13 +94,18 @@
#define SECTION_PROLOGUE(name, options, align) name options : align

/*
 * The SECTION_AT_PROLOGUE() macro is similar to SECTION_PROLOGUE() except
 * that, in addition, the address at which the section is to be loaded is
 * specified.
 * As for SECTION_PROLOGUE(), except that this one must (!) be used
 * for data sections which on XIP platforms will have differeing
 * virtual and load addresses (i.e. they'll be copied into RAM at
 * program startup).  Such a section must (!) also use
 * GROUP_LINK_IN_LMA to specify the correct output load address.
 */

#define SECTION_AT_PROLOGUE(name, options, align, addr) \
	name options : align AT(addr)
#ifdef CONFIG_XIP
#define SECTION_DATA_PROLOGUE(name, options, align) \
	name options : ALIGN_WITH_INPUT align
#else
#define SECTION_DATA_PROLOGUE(name, options, align) name options : align
#endif

#define SORT_BY_NAME(x) SORT(x)
#define OPTIONAL
Loading