zephyr/arch/common/rom_start_offset.ld

22 lines
683 B
Plaintext
Raw Permalink Normal View History

/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
arch/common: Fix moving location counter backwards when using LLD In GNU LD, the location counter (the 'dot' variable) always refers to the byte offset from the start of current object as mentioned in documentation[1]: ``` '.' actually refers to the byte offset from the start of the current containing object. Normally this is the SECTIONS statement, whose start address is 0, hence '.' can be used as an absolute address. If '.' is used inside a section description however, it refers to the byte offset from the start of that section, not an absolute address. ``` For example, if the section 'rom_start': rom_start : { . = 0x400; _vector_start = ABSOLUTE(.); } > FLASH has a starting address of 0x8000000, then _vector_start will be 0x8000400 However, behavior of LLVM LLD is quite different, the value of the location counter is always absolute (see discussion [2]), so in the example above, the linker will return error, because it will interpret '. = 0x400' as an attempt to move the location counter backwards. It could be fixed by changing line to '. += 0x400' (#54796) which will move the location counter by 0x400 for both linkers, but it would work only when we are at the beginning of section. Consider the following example: rom_start : { . = 0x400; KEEP(*(.boot_hdr.conf)) . = 0x1000; KEEP(*(.boot_hdr.ivt)) KEEP(*(.boot_hdr.data)) KEEP(*(.boot_hdr.dcd_data)) . = 0x2000; _vector_start = .; } > FLASH In this case, _vector_start will be 0x2000, but if we change '. = 0x2000' to '. += 0x2000', then the value of _vector_start depends on size of data in input sections (but it's 0x3000 at least). Actually, this example comes from final linker script when compiling firmware for mimxrt1170_evk_cm7 board. This board failed to boot (#55296) after #54796 was merged. This patch introduces method compatible with both linkers. We calculate relative offset from the beginning of the section and use that value to calculate number of bytes by which we should move the location counter to get CONFIG_ROM_START_OFFSET. [1] https://sourceware.org/binutils/docs/ld/Location-Counter.html [2] https://discourse.llvm.org/t/lld-location-counter-inside-objects Signed-off-by: Patryk Duda <pdk@semihalf.com>
2023-05-26 13:47:08 +02:00
/*
* The line below this comment is equivalent to '. = CONFIG_ROM_START_OFFSET'
* as interpreted by GNU LD, but also compatible with LLVM LLD.
*
* Simple assignment doesn't work for LLVM LLD, because the dot inside section
* is absolute, so assigning offset here results in moving location counter
* backwards.
*
* We can't use '. += CONFIG_ROM_START_OFFSET' here because there might be some
* other files included before this file.
*
* Symbol __rom_start_address is defined in rom_start_address.ld
*/
. += CONFIG_ROM_START_OFFSET - (. - __rom_start_address);
. = ALIGN(4);